ural 1671
题目:http://acm.timus.ru/problem.aspx?space=1&num=1671
题意:给你 N 个点 和 M 条边,然后删除其中的一些边,问删除一些边后剩余的几块
用并查集逆向的把要删的边加入进去,加入的时候统计。先是全部输入,然后标记要删除的边,把不需要删除的边用并查集合并,然后逆向的把要删的边加上,每加一条边时看看现在的快有几个
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 typedef long long ll; 2 #define N 100001 3 int num[N]; 4 int f[N]; 5 int cnt[N]; 6 struct node 7 { 8 int s,e; 9 int is; 10 }eage[N]; 11 int find(int x) 12 { 13 if(x != f[x]) return f[x] = find(f[x]); 14 else return f[x]; 15 } 16 int hebing(int s,int e) 17 { 18 int root1 = find(s); 19 int root2 = find(e); 20 if(root1 == root2) return 0; 21 else {f[root1] = root2; return 1;} 22 } 23 int main() 24 { 25 int i; 26 int n,m; 27 //freopen("data.txt","r",stdin); 28 while(cin>>n>>m) 29 { 30 //memset(num,0,sizeof(num)); 31 for(i = 1; i <= n; i++) 32 f[i] = i; 33 _clr(num,0); 34 _clr(eage,0); 35 _clr(cnt,0); 36 for(i = 1;i <= m; i++) 37 { 38 scanf("%d%d",&eage[i].s,&eage[i].e); 39 eage[i].is = 1; 40 } 41 int q; 42 scanf("%d",&q); 43 for(i = 0; i < q; i++) 44 { 45 scanf("%d",&num[i]); 46 eage[num[i]].is = 0; // 标记删除的边 47 } 48 int ans = 0; 49 for(i = 1; i <= m; i++) 50 { 51 if(eage[i].is == 0) continue; 52 if(hebing(eage[i].s,eage[i].e)) ans ++; // 统计原始的块数 53 } 54 for(i = q - 1; i >= 0; i--) // 逆向加边 55 { 56 cnt[i] = n - ans; 57 if(hebing(eage[num[i]].s,eage[num[i]].e)) ans++; 58 } 59 for(i = 0; i < q; i++) 60 { 61 if(i != 0) printf(" "); 62 printf("%d",cnt[i]); 63 } 64 printf("\n"); 65 } 66 return 0; 67 }