HDU 4612 Warm up
Posted IKnowYou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4612 Warm up相关的知识,希望对你有一定的参考价值。
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4612
解题思路:
题的大意是有N个种植园,有M条水渠相连。这就是一个强连通的无向图,他不想要这个图中存在有桥,如果添加一条边,剩余的桥的最小数量。
本题的答案先用Tarjan进行缩点。在这个过程就可以计算出桥的数量。然后怎样添加一条边使的桥的数量最少呢?
答案:桥-缩点形成树的直径。
如何求树的直径:
有两种方法
1. 对树进行广度优先搜索,然后以广度优先搜索最后一个访问的点进行优先搜索,然后深度优先搜索形成的这颗树的深度就是树的直径。
2.对树进行深度优先搜索,以深度最深的点,在进行一次深度优先搜索,然后深度优先搜索形成的这颗树的深度就是就是树的直径
注意本题有重边。
实现代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 const int MAXN=200010; 9 const int MAXM=2000010; 10 11 struct Edge{ 12 int to,next; 13 bool cut; //标记是否是桥 14 bool meg; //标记是否是重边 15 }edges[MAXM]; 16 17 int head[MAXN],tot; 18 19 void init(){ 20 memset(head,-1,sizeof(head)); 21 tot=0; 22 } 23 24 void addEdge(int u,int v,bool meg){ 25 edges[tot].to=v; 26 edges[tot].meg=meg; 27 edges[tot].next=head[u]; 28 edges[tot].cut=false; 29 head[u]=tot++; 30 } 31 32 int LOW[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN]; 33 bool Instack[MAXN]; 34 int bridge,Index,top; 35 int block; 36 37 void Tarjan(int u,int pre,bool meg){ 38 DFN[u]=LOW[u]=++Index; 39 Stack[top++]=u; 40 Instack[u]=true; 41 42 int v; 43 for(int i=head[u];i!=-1;i=edges[i].next){ 44 v=edges[i].to; 45 if(v==pre&&(!meg)) continue; 46 47 if(!DFN[v]){ 48 Tarjan(v,u,edges[i].meg); 49 50 if(LOW[u]>LOW[v]) LOW[u]=LOW[v]; 51 52 if(LOW[v]>DFN[u]){ 53 bridge++; 54 edges[i].cut=true; 55 edges[i^1].cut=true; 56 } 57 }else if(Instack[v]&&LOW[u]>DFN[v]) LOW[u]=DFN[v]; 58 } 59 60 if(DFN[u]==LOW[u]){ 61 block++; 62 do{ 63 v=Stack[--top]; 64 Instack[v]=false; 65 Belong[v]=block; 66 }while(v!=u); 67 } 68 } 69 70 vector<int>tree[MAXN]; 71 int dep[MAXN]; 72 73 //计算树的深度 74 void dfs(int u){ 75 76 for(int i=0;i<tree[u].size();i++){ 77 int v=tree[u][i]; 78 79 if(dep[v]!=-1) continue; 80 dep[v]=dep[u]+1; 81 dfs(v); 82 } 83 } 84 85 void solve(int n){ 86 memset(DFN,0,sizeof(DFN)); 87 memset(Instack,0,sizeof(Instack)); 88 Index=top=bridge=block=0; 89 90 91 Tarjan(1,0,false); 92 for(int i=1;i<=block;i++) 93 tree[i].clear(); 94 95 for(int i=1;i<=n;i++) 96 for(int j=head[i];j!=-1;j=edges[j].next) 97 if(edges[j].cut) 98 tree[Belong[i]].push_back(Belong[edges[j].to]); 99 100 memset(dep,-1,sizeof(dep)); 101 int k=1; 102 dep[1]=0; 103 dfs(1); 104 for(int i=1;i<=block;i++){ 105 if(dep[k]<dep[i]) 106 k=i; 107 } 108 109 memset(dep,-1,sizeof(dep)); 110 dep[k]=0; 111 int ans=0; 112 dfs(k); 113 114 for(int i=1;i<=block;i++) 115 ans=max(ans,dep[i]); 116 117 printf("%d\\n",bridge-ans); 118 } 119 120 struct node{ 121 int u,v; 122 bool operator <(const node &rhs) const{ 123 if(u!=rhs.u) 124 return u<rhs.u; 125 else 126 return v<rhs.v; 127 } 128 }; 129 130 node nd[MAXM]; 131 132 int main(){ 133 int n,m; 134 while(scanf("%d%d",&n,&m)==2){ 135 if(n==0&&m==0) break; 136 init(); 137 138 for(int i=0;i<m;i++){ 139 int u,v; 140 scanf("%d%d",&u,&v); 141 if(u==v) continue; 142 if(u>v) swap(u,v); 143 nd[i].u=u; 144 nd[i].v=v; 145 } 146 sort(nd,nd+m); 147 148 for(int i=0;i<m;i++){ 149 if(i==0||nd[i].u!=nd[i-1].u||nd[i].v!=nd[i-1].v){ 150 if(i<m-1&&nd[i].u==nd[i+1].u&&nd[i].v==nd[i+1].v){ 151 addEdge(nd[i].u,nd[i].v,true); 152 addEdge(nd[i].v,nd[i].u,true); 153 }else{ 154 addEdge(nd[i].u,nd[i].v,false); 155 addEdge(nd[i].v,nd[i].u,false); 156 } 157 } 158 } 159 solve(n); 160 } 161 }
以上是关于HDU 4612 Warm up的主要内容,如果未能解决你的问题,请参考以下文章