1.1013 Battle Over Cities
思路:
N个点M个边K次查询,每次查询的结果等价于孤立点的个数-1
外循环:每次查询,内循环:存连通除查询点外的所有边,最终输出孤立点个数-1 O(KM)<1e8
代🐎:
// N个点M个边K次查询,每次查询的结果等价于孤立点的个数-1
// 外循环:每次查询,内循环:存连通除查询点外的所有边,最终输出孤立点个数-1 O(KM)<1e8
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1010;
const int M = 500010;
int fa[N];
struct Edge{
int a, b;
}e[M];
int find(int x)
{
if(fa[x] != x) fa[x] = find(fa[x]);
return fa[x]; // 返回的是fa[x]而不是x
}
int main()
{
int n, m, k;
cin >> n >> m >> k;
for(int i = 0; i < m; i++)
{
scanf("%d %d", &e[i].a, &e[i].b);
}
while(k --)
{
int city;
cin >> city;
for(int i = 1; i <= n; i ++) fa[i] = i; // 每次循环都要初始化
int cnt = n - 1;
for(int j = 0; j < m; j ++)
{
if(e[j].a != city && e[j].b != city)
{
int pa = find(e[j].a);
int pb = find(e[j].b);
if(pa != pb) // 不连通就合并
{
fa[pa] = pb;
cnt --;
}
}
}
cout << cnt - 1 << endl;
}
return 0;
}
2.PAT 1118 Birds in Forest
思路:
并查集:也是统计连通块数目,树的数目=连通块个数,鸟的个数用hash和sum维护一下,询问即判定是否连通
复杂度 O(NK + Q) = 1e5
代🐎:
// 并查集:也是统计连通块数目,树的数目=连通块个数,鸟的个数用hash和sum维护一下,询问即判定是否连通
// 复杂度 O(NK + Q) = 1e5
#include <iostream>
#include <cstring>
using namespace std;
const int N = 10010;
int fa[N], b[N];
bool st[N];
int find(int x)
{
if(fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
int main()
{
int n, k, q;
cin >> n;
for(int i = 1; i <= N; i ++) fa[i] = i;
memset(st, 0, sizeof st);
int birds = 0;
for(int i = 1; i <= n; i ++)
{
cin >> k;
for(int j = 1; j <= k; j ++)
{
cin >> b[j];
int bird = b[j];
if(!st[bird]) birds ++;
st[bird] = true;
}
for(int j = 1; j < k; j ++) // 连通同一棵树上所有鸟
{
int p = b[j], q = b[j + 1];
p = find(p), q = find(q);
if(p != q)
{
fa[p] = q;
}
}
}
int trees = 0;
for(int i = 1; i <= birds; i ++)
{
if(fa[i] == i) trees ++;
}
cout << trees << " " << birds << endl;
cin >> q;
while(q --)
{
int x, y;
cin >> x >> y;
int px = find(x), py = find(y);
if(px == py) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}