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的主要内容,如果未能解决你的问题,请参考以下文章

HDU4612Warm up

HDU 4612 Warm up

HDU4612:Warm up(缩点+树的直径)

Warm up HDU - 4612( 树的直径 边双连通分量)

hdu4612-Warm up(边的双连通分量)

HDU 4612 Warm up —— (缩点 + 求树的直径)