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 }

浙公网安备 33010602011771号