11/17-提高组笔记
2024-11-17 11:50:37
~团伙
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<stack>
#include<sstream>
#include<set>
#include<time.h>
#include<stdlib.h>
#include<unordered_map>
#define ll long long
#define ull unsigned long long
#define eps 1e-10
#define INF 1e9
#define delta 0.996
#define T 3000
#define pi acos(-1.0)
#define ld long double
using namespace std;
const ll mod1=1e9+7;
const ll mod2=998244353;
const int maxn = 2e5 + 10;
const int maxm = 2e5 + 10;
const ll inf=1e18L;
typedef pair<int,int>Pii;
typedef pair<int,ll>Pil;
using namespace std;
int father[5010], n, m, di[5010], ans;
int find(int x)
{
if(father[x] == x) return x;
else return father[x] = find(father[x]);
}
void unite(int x, int y)
{
x = find(x);
y = find(y);
if(x == y) return;
father[x] = y;
}
int same(int x, int y)
{
if(find(x) == find(y)) return 1;
else return 0;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i++)
{
father[i] = i;
}
while(m--)
{
char c;
int x, y;
cin >> c >> x >> y;
if(c == 'F') unite(x, y);
else
{
// x之前还有别的敌人 di[x]
// di[x] 和 y 是不是就有共同的敌人 x
// 所以 di[x] 和 y 是好朋友,要合并
if(di[x] == 0) di[x] = find(y); //没敌人
else unite(di[x], y); //有敌人
if(di[y] == 0) di[y] = find(x);
else unite(di[y], x);
}
}
for(int i = 1; i <= n; i++)
{
if(find(i) == i) ans++;
}
cout << ans << '\n';
return 0;
}
买礼物
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<stack>
#include<sstream>
#include<set>
#include<time.h>
#include<stdlib.h>
#include<unordered_map>
#define ll long long
#define ull unsigned long long
#define eps 1e-10
#define INF 1e9
#define delta 0.996
#define T 3000
#define pi acos(-1.0)
#define ld long double
using namespace std;
const ll mod1=1e9+7;
const ll mod2=998244353;
const int maxn = 2e5 + 10;
const int maxm = 2e5 + 10;
const ll inf=1e18L;
typedef pair<int,int>Pii;
typedef pair<int,ll>Pil;
using namespace std;
int father[100010], A, B, n, cnt, cnt2;
int find(int x)
{
if(father[x] == x) return x;
else return father[x] = find(father[x]);
}
void unite(int x, int y)
{
x = find(x);
y = find(y);
if(x == y) return;
father[x] = y;
}
int same(int x, int y)
{
if(find(x) == find(y)) return 1;
else return 0;
}
struct edge
{
int u, v, cost;
}e[200010];
int cmp(edge e1, edge e2)
{
return e1.cost < e2.cost;
}
int kruskal()
{
sort(e + 1, e + 1 + n, cmp);
int res = 0;
for(int i = 1; i <= n - cnt2; i++)
{
if(same(e[i].u, e[i].v) == 0)
{
res += e[i].cost;
cnt++;
unite(e[i].u, e[i].v);
}
}
return res;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> A >> B;
for(int i = 1; i <= B; i++)
{
father[i] = i;
}
for(int i = 1; i <= B; i++)
{
for(int j = 1; j <= B; j++)
{
int x;
cin >> x;
if(i < j && x != 0)
{
n++;
e[n] = {i, j, x};
if(e[n].cost > A) cnt2++;
}
}
}
int ans = kruskal();
if(cnt == B + 1) cout << ans + A << '\n';
else cout << ans + A + (B - cnt - 1) * A << '\n';
return 0;
}
prim 算法
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
#include<stack>
#include<sstream>
#include<set>
#include<time.h>
#include<stdlib.h>
#include<unordered_map>
#define ll long long
#define ull unsigned long long
#define eps 1e-10
#define INF 1e9
#define delta 0.996
#define T 3000
#define pi acos(-1.0)
#define ld long double
using namespace std;
const ll mod1=1e9+7;
const ll mod2=998244353;
const int maxn = 2e5 + 10;
const int maxm = 2e5 + 10;
const ll inf=1e18L;
typedef pair<int,int>Pii;
typedef pair<int,ll>Pil;
using namespace std;
//pair类型的优先队列默认用 .first 排序
//要把长度存在first位置,点存second
priority_queue<Pii, vector<Pii>, greater<Pii> >q;
struct edge
{
int v, cost;
};
vector<edge>G[5010];
// vis 记录一个点是否已经选过
// dist 记录选入这个点的最小代价
int n, m, vis[5010], dist[5010], ans, cnt;
void prim()
{
for(int i = 0; i <= n; i++) dist[i] = 1e9;
dist[1] = 0;
q.push({0, 1});
while(q.empty() == 0)
{
Pii now = q.top(); q.pop();
if(vis[now.second] == 1) continue;
ans += now.first;
cnt++;
vis[now.second] = 1;
if(cnt == n) break;
// 松弛
// 看一下 now.second 能连接着哪些点 : vector 遍历
// G[1] = {2, 3, 4, 5};
// G[1][0] = 2;
// G[1][1] = 3;
int siz = (int)G[now.second].size();
for(int i = 0; i < siz; i++)//必须从0开始
{
edge e = G[now.second][i];
// edge 结构体中有 e.v 表示点的编号 e.cost 表示边长
// 如果 当前的 e.cost 小于 之前的代价
// 说明当前的代价更好,我们就要更新,并把新的代价加入优先队列
// eg:假设当前加入 2 号点的代价为 5
// 即 e.cost = 5
// 而 之前 2 号点可以被一号点加入,代价为 10
// 即 dist[2] = 10;
// 所以此时需要判断 e.cost < dist[2] (5 < 10)
// dist[2] 由 10 换成 5
// 并把新的代价加入优先队列
// e.cost 就是使得 e.v 选入的代价
if(e.cost < dist[e.v])
{
dist[e.v] = e.cost;
q.push({e.cost, e.v});
}
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for(int i = 1; i <= m; i++)
{
int a, b, c;
cin >> a >> b >> c;
G[a].push_back({b, c});
G[b].push_back({a, c});
}
prim();
if(cnt == n) cout << ans << '\n';
else cout << "orz\n";
return 0;
}
我们会审查剪贴板内容,并对发布不合适内容的同学进行相应的处理