【题意】 给出一张无向连通图,求至少连几条边可以变成边双连通图
【思路】求出边-双连通分量,缩点就成了一棵树,求这棵树里的出度为1 的点num ,即叶子结点的个数,结果是(num+1)/2;
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<stack> 5 #include<vector> 6 using namespace std; 7 int pre[1002],low[1002],n,adj[1002],num,c,du[1002]; 8 struct E 9 { 10 int to; 11 int next; 12 } edge[500000]; 13 14 void add(int a,int b) 15 { 16 edge[num].to=b; 17 edge[num].next=adj[a]; 18 adj[a]=num++; 19 } 20 21 int dfs(int u,int fa) 22 { 23 int i,v,lowv; 24 pre[u]=low[u]=c++; 25 for(i=adj[u]; i!=-1; i=edge[i].next) 26 { 27 int v; 28 v=edge[i].to; 29 if(v!=fa&&pre[v]<pre[u]) 30 { 31 if(!pre[v]) 32 { 33 lowv=dfs(v,u); 34 low[u]=min(low[u],lowv); 35 } 36 else if(pre[v]&&v!=fa) 37 low[u]=min(low[u],pre[v]); 38 } 39 } 40 return low[u]; 41 } 42 43 int main() 44 { 45 int a,b,m,i,v; 46 while(~scanf("%d%d",&n,&m)) 47 { 48 memset(adj,-1,sizeof(adj)); 49 num=0; 50 while(m--) 51 { 52 scanf("%d%d",&a,&b); 53 add(a,b); 54 add(b,a); 55 } 56 c=1; 57 memset(pre,0,sizeof(pre)); 58 for(int i=1; i<=n; i++) 59 if(pre[i]==0) 60 dfs(i,-1); 61 memset(du,0,sizeof(du)); 62 for(int u=1; u<=n; u++) 63 { 64 for(i=adj[u]; i!=-1; i=edge[i].next) 65 { 66 int v; 67 v=edge[i].to; 68 if(low[u]!=low[v]) 69 { 70 du[low[u]]++; 71 du[low[v]]++; 72 } 73 } 74 } 75 int ans=0; 76 for(int i=0; i<=n; i++) 77 if(du[i]/2==1) 78 ans++; 79 printf("%d ",(ans+1)/2); 80 } 81 return 0; 82 }