Codeforces Beta Round #25 (Div. 2 Only) D. Roads not only in Berland(DFS+并查集)

 

题目大意

 

给了一个无向图,n(2<=n<=1000) 个节点 n-1 条边,每天拆一条边并新建一条边,最终使得所有的顶点连通(其实形成一棵树)

问:最少需要几天,并且输出每天拆掉的边和新建的边

 

做法分析

 

首先,我们可以把每条边存下来,然后利用 DFS,遍历所有的顶点一遍,遍历的过程中,经过的边就是树边(也就是所有的不拆掉的边),剩下的所有边统统要拆掉

利用并查集,把每个连通块用一个点代表,并统计这个连通快中需要删掉的边的个数(DFS过程中没有遍历到的边的个数)

这里,我们需要注意到这样一个性质:只有 n-1 条边,那么,图中肯定存在一个联通快,它是一棵树或者一个孤立的节点

最少需要的天数肯定是不能遍历到的边的数量

那么:每一天,我们删掉一条没有遍历到的边,从这个连通块中,并引一条边出去到另一个全是树边的连通分量,注意更新删掉边以后那个连通分量的相关信息

 

参考代码

 

D. Roads not only in Berland
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 
 5 using namespace std;
 6 
 7 const int N=1006;
 8 
 9 struct Edge
10 {
11     int s, t, next;
12     bool flag;
13     void init(int a, int b, int c)
14     {
15         s=a, t=b, next=c, flag=false;
16     }
17 } edge[N*2];
18 int head[N], tot;
19 
20 void add_edge(int s, int t)
21 {
22     edge[tot].init(s, t, head[s]);
23     head[s]=tot++;
24     edge[tot].init(t, s, head[t]);
25     head[t]=tot++;
26 }
27 
28 int n, cnt[N], fa[N];
29 bool vs[N];
30 
31 void DFS(int u, int pre)
32 {
33     vs[u]=1;
34     for(int e=head[u]; e!=-1; e=edge[e].next)
35     {
36         int v=edge[e].t;
37         if(v==pre || vs[v]) continue;
38         edge[e].flag=1, edge[e^1].flag=1;
39         DFS(v, u);
40     }
41 }
42 
43 int find_fa(int x)
44 {
45     if(fa[x]!=x) fa[x]=find_fa(fa[x]);
46     return fa[x];
47 }
48 
49 int main()
50 {
51     scanf("%d", &n);
52     memset(head, -1, sizeof head);
53     tot=0;
54     for(int i=1; i<=n; i++) fa[i]=i;
55     for(int i=1, a, b; i<n; i++)
56     {
57         scanf("%d%d", &a, &b);
58         add_edge(a, b);
59         int f1=find_fa(a);
60         int f2=find_fa(b);
61         if(f1!=f2) fa[f1]=f2;
62     }
63     memset(vs, 0, sizeof vs);
64     for(int i=1; i<=n; i++) if(!vs[i]) DFS(i, -1);
65 
66     memset(cnt, 0, sizeof cnt);
67     int ans=0;
68     for(int i=0; i<tot; i+=2) if(!edge[i].flag)
69     {
70         ans++;
71         cnt[find_fa(edge[i].s)]++, cnt[find_fa(edge[i].t)]++;
72     }
73 
74     printf("%d\n", ans);
75     for(int e=0; e<tot; e+=2)
76     {
77         if(edge[e].flag) continue;
78         printf("%d %d ", edge[e].s, edge[e].t);
79         for(int i=1; i<=n; i++)
80         {
81             if(cnt[find_fa(i)]!=0 || find_fa(i)==find_fa(edge[e].s)) continue;
82             printf("%d %d\n", edge[e].s, i);
83             fa[find_fa(i)]=find_fa(edge[e].s);
84             break;
85         }
86         cnt[find_fa(edge[e].s)]--, cnt[find_fa(edge[e].t)]--;
87     }
88     return 0;
89 }

 

题目链接 & AC通道

 

Codeforces Beta Round #25 (Div. 2 Only) D. Roads not only in Berland

 

 

 

posted @ 2013-04-21 19:34  jianzhang.zj  阅读(237)  评论(0编辑  收藏  举报