ural 1671

题目:http://acm.timus.ru/problem.aspx?space=1&num=1671

题意:给你 N 个点 和 M 条边,然后删除其中的一些边,问删除一些边后剩余的几块

用并查集逆向的把要删的边加入进去,加入的时候统计。先是全部输入,然后标记要删除的边,把不需要删除的边用并查集合并,然后逆向的把要删的边加上,每加一条边时看看现在的快有几个

View Code
 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 }
posted @ 2012-09-08 10:15  AC_Girl  阅读(198)  评论(0编辑  收藏  举报