边双联通问题求解(构造边双连通图)POJ3352(Road Construction)
题目链接:传送门
题目大意:给你一副无向图,问至少加多少条边使图成为边双联通图
题目思路:tarjan算法加缩点,缩点后求出度数为1的叶子节点个数,需要加边数为(leaf+1)/2
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <cstring> 7 #include <stack> 8 #include <cctype> 9 #include <queue> 10 #include <string> 11 #include <vector> 12 #include <set> 13 #include <map> 14 #include <climits> 15 #define lson root<<1,l,mid 16 #define rson root<<1|1,mid+1,r 17 #define fi first 18 #define se second 19 #define ping(x,y) ((x-y)*(x-y)) 20 #define mst(x,y) memset(x,y,sizeof(x)) 21 #define mcp(x,y) memcpy(x,y,sizeof(y)) 22 #define Min(x,y) (x<y?x:y) 23 #define Max(x,y) (x>y?x:y) 24 using namespace std; 25 #define gamma 0.5772156649015328606065120 26 #define MOD 1000000007 27 #define inf 0x3f3f3f3f 28 #define N 5005 29 #define maxn 10005 30 typedef long long LL; 31 typedef pair<int,int> PII; 32 33 vector<int>V[1005]; 34 int n,m,hcnt,deep; 35 struct Node{ 36 int to,next; 37 Node(){} 38 Node(int a,int b):to(a),next(b){} 39 }node[N]; 40 int head[N],vis[N],low[N],dfn[N]; 41 int d[N]; 42 43 inline void add(int x,int y){ 44 node[hcnt]=Node(y,head[x]); 45 head[x]=hcnt++; 46 } 47 48 inline void init(){ 49 mst(d,0); 50 mst(vis,0); vis[1]=1; 51 mst(head,-1); 52 hcnt=0; 53 deep=1; 54 low[1]=dfn[1]=1; 55 } 56 57 void dfs(int x,int father){ 58 for(int i=head[x];~i;i=node[i].next){ 59 int e=node[i].to; 60 if(e==father)continue; 61 if(vis[e])low[x]=min(low[x],dfn[e]); 62 else{ 63 vis[e]=1; 64 low[e]=dfn[e]=++deep; 65 dfs(e,x); 66 low[x]=min(low[x],low[e]); 67 } 68 } 69 } 70 71 int main(){ 72 int i,j,group,Case=0,x,y; 73 while(scanf("%d%d",&n,&m)!=EOF){ 74 for(i=0;i<=n;++i)V[i].clear(); 75 init(); 76 while(m--){ 77 scanf("%d%d",&x,&y); 78 add(x,y); 79 add(y,x); 80 V[x].push_back(y); ///两点之间联通 81 V[y].push_back(x); ///在缩点之后用于计算度数 82 } 83 dfs(1,-1); ///tarjan算法 84 int leaf=0; 85 for(i=1;i<=n;++i) 86 if(V[i].size()) 87 for(j=0;j<V[i].size();++j){ 88 int e=V[i][j]; 89 if(low[i]!=low[e]) 90 d[low[i]]++; 91 } 92 for(i=0;i<=deep;++i) 93 if(d[i]==1)++leaf; 94 printf("%d\n",(leaf+1)/2); 95 } 96 return 0; 97 }