POJ3177 Redundant Paths

POJ3177 Redundant Paths

题意:

  有一个由f个点,r条边组成的无向图,求至少加几条边可以使这个图成为一个双连通分量(即图中任何一条边去掉后该图仍然是一个连通图)。

思路:

  用tarjan对无向图进行缩点。

  缩点后,对图中所有只有一条边连接的点之间连一条边(不是两两之间连边,而是两个点拿出来连一条边),如果有奇数个只有一条边连接的点(就是说两个点两个点连完后还剩一个点),那么给他也随便连条边。

  这样做可以保证一定有一种连法使该图成为一个双连通分量。

  最后的答案是ceil(度数为1的点的个数/2)

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <stack>
 5 using namespace std;
 6 #define MAXN 10010
 7 #define MAXM 100010
 8 struct Node{
 9     int u,v;
10     Node(){}
11     Node(int u,int v):u(u),v(v){}
12 }p[MAXM];
13 int head[MAXN],Next[MAXM],low[MAXN],dfn[MAXN],color[MAXN],du[MAXN];
14 bool vis[MAXN];
15 stack<int> mstack;
16 int i,j,k,m,n,u,v,tot,times,colnum,ans;
17 void addNode(int u,int v){
18     p[++tot]=Node(u,v);
19     Next[tot]=head[u],head[u]=tot;
20     p[++tot]=Node(v,u);
21     Next[tot]=head[v],head[v]=tot;
22 }
23 void tarjan(int pre,int src){
24     low[src]=dfn[src]=++times;
25     mstack.push(src);
26     vis[src]=true;
27     bool flag=false;
28     for(int i=head[src];i+1;i=Next[i]){
29         if(p[i].v==pre&&!flag) {
30             flag=true;
31             continue;
32         }
33         if(!dfn[p[i].v]){
34             tarjan(src,p[i].v);
35             low[src]=min(low[src],low[p[i].v]);
36         }else{
37             low[src]=min(low[src],dfn[p[i].v]);
38         }
39     }
40     if(dfn[src]==low[src]){
41         ++colnum;
42         int tmp;
43         do{
44             tmp=mstack.top(); mstack.pop();
45             color[tmp]=colnum;
46             vis[tmp]=false;
47         }while(tmp!=src);
48     }
49 }
50 int main(){
51     memset(head,-1,sizeof(head));
52     memset(low,0,sizeof(low));
53     memset(dfn,0,sizeof(dfn));
54     memset(vis,0,sizeof(vis));
55     memset(du,0,sizeof(du));
56     memset(color,0,sizeof(color));
57     tot=-1,times=0,colnum=0;
58     scanf("%d%d",&n,&m);
59     for(i=1;i<=m;i++){
60         scanf("%d%d",&u,&v);
61         addNode(u,v);
62     }
63     for(i=1;i<=n;i++){
64         if(!dfn[i]) tarjan(-1,i);
65     }
66     for(i=1;i<=n;i++){
67         for(j=head[i];j+1;j=Next[j]){
68             if(color[p[j].u]!=color[p[j].v])du[color[p[j].u]]++,du[color[p[j].v]]++;
69         }
70     }
71     ans=0;
72     for(i=1;i<=colnum;i++) if(du[i]==2) ans++;
73     printf("%d\n",(ans+1)/2);
74     return 0;
75 }

 

posted @ 2018-10-03 22:43  EternalBlue  阅读(144)  评论(0)    收藏  举报