HDOJ4612双连通分量缩点+找树的直径

Posted MekakuCityActor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDOJ4612双连通分量缩点+找树的直径相关的知识,希望对你有一定的参考价值。

http://acm.hdu.edu.cn/showproblem.php?pid=4612

Warm up

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 8309    Accepted Submission(s): 1905

Problem Description
  N planets are connected by M bidirectional channels that allow instant transportation. It‘s always possible to travel between any two planets through these channels.
  If we can isolate some planets from others by breaking only one channel , the channel is called a bridge of the transportation system.
People don‘t like to be isolated. So they ask what‘s the minimal number of bridges they can have if they decide to build a new channel.
  Note that there could be more than one channel between two planets.
 
Input
  The input contains multiple cases.
  Each case starts with two positive integers N and M , indicating the number of planets and the number of channels.
  (2<=N<=200000, 1<=M<=1000000)
  Next M lines each contains two positive integers A and B, indicating a channel between planet A and B in the system. Planets are numbered by 1..N.
  A line with two integers ‘0‘ terminates the input.
 
Output
  For each case, output the minimal number of bridges after building a new channel in a line.
 
Sample Input
4 4 1 2 1 3 1 4 2 3 0 0
 
Sample Output
0
题目大意:给一个连通图,求加一条边之后最少还有多少个桥。
题目分析:首先看到要求是"改造桥",则先进行缩点,由于是改造桥,所以进行边双连通的缩点,然后求树的直径【树上桥最多的一条路】,则最后结果ans=原来桥数-直径。
【说坑点】:
【1】
无向图的缩点与有向图不一样,有向图如果一条边的两端点不在一个连通分量里面则加一条边即可,也就是可以使用原来的结构体数组【因为是最多一换一】
而无向图中,一条边两端点不在同一个连通分量里面则需要加入两条边【即会出现一换二的情况,则就不能直接放进原本的结构体数组了,否则会覆盖原数组数据】【WA..】
【2】
无向图的边数组的存储大小应该是 2 * MAXN 而不是 MAXN...【无限RE  】
【3】
对桥什么的判断一定要用 low[ v ] > dfn[ u ] ,而不能用 low[ v ] > low[ u ]因为low[ u ]是一直随孩子变化的,而只有和 dfn[ u ]这个用于不变的变量比较才能得到正确的位置关系。
【无限wa...】
  1 #include <stdio.h>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <string.h>
  5 #include <queue>
  6 #include <vector>
  7 using namespace std;
  8 
  9 const int MAXN = 200010;
 10 const int MAXM = 1000015;
 11 struct Edge
 12 {
 13     int to,from,next;
 14 }edge[MAXM*2],eedge[MAXM*2];
 15 int head[MAXN],edge_cnt;
 16 int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~block
 17 int Index,top;
 18 int block;
 19 bool Instack[MAXN];
 20 int bridge;    
 21 int n,m;
 22 int key,d,vis[MAXN];
 23 void addedge(int u,int v)
 24 {
 25     edge[edge_cnt].from=u;
 26     edge[edge_cnt].to = v;edge[edge_cnt].next = head[u];
 27     head[u] = edge_cnt++;
 28 }
 29 void addedge2(int u,int v)
 30 {
 31     eedge[edge_cnt].from=u;
 32     eedge[edge_cnt].to = v;eedge[edge_cnt].next = head[u];
 33     head[u] = edge_cnt++;
 34 }
 35 void Tarjan(int u,int id)
 36 {
 37     int v;
 38     Low[u] = DFN[u] = ++Index;
 39     Stack[top++] = u;
 40     Instack[u] = true;
 41     for(int i = head[u];i != -1;i = edge[i].next)
 42     {
 43         v = edge[i].to;
 44         if( i == (id^1))continue;
 45         if( !DFN[v] )
 46         {
 47             Tarjan(v,i);
 48             if(Low[u] > Low[v])Low[u] = Low[v];
 49             if(Low[v] > DFN[u])
 50             {
 51                 bridge++;
 52             }
 53         }
 54         else if(Instack[v] && Low[u] > DFN[v])
 55              Low[u] = DFN[v];
 56     }
 57     if(Low[u] == DFN[u])
 58     {
 59         block++;
 60         do
 61         {
 62             v = Stack[--top];
 63             Instack[v] = false;
 64             Belong[v] = block;
 65         }
 66         while( v != u );
 67     }
 68 }
 69 void dfs(int u,int len)
 70 {
 71     vis[u]=1;
 72     if(len > d)
 73     {
 74         d=len;
 75         key=u;
 76     }
 77     for(int i = head[u]; i != -1 ; i=eedge[i].next)
 78     {
 79         int v=eedge[i].to;
 80         if(!vis[v])
 81         {
 82             dfs(v,len+1);
 83         }
 84     }
 85     return;
 86 }
 87 void init()
 88 {
 89     edge_cnt=0;
 90     memset(head,-1,sizeof(head));
 91 }
 92 void solve()
 93 {
 94     memset(DFN,0,sizeof(DFN));
 95     memset(Low,0,sizeof(Low));
 96     memset(Belong,0,sizeof(Belong));
 97     memset(Instack,false,sizeof(Instack));
 98     Index = top = block = bridge = 0;
 99     Tarjan(1,-1);
100     int orz=edge_cnt;
101     edge_cnt=0;
102     memset(head,-1,sizeof(head));
103     for(int i = 0 ; i < orz ; i++)
104     { 
105         if(Belong[edge[i].to]!=Belong[edge[i].from])
106         {
107             
108             addedge2(Belong[edge[i].to],Belong[edge[i].from]);
109             addedge2(Belong[edge[i].from],Belong[edge[i].to]);
110         }
111     }
112     d=0;    key=0;
113     memset(vis,0,sizeof(vis));
114     dfs(1,0);
115     d=0;//    cout << key <<endl;
116     memset(vis,0,sizeof(vis));
117     dfs(key,0);
118 
119     cout << bridge-d<<endl;
120 }
121 int main()
122 {
123     scanf("%d%d",&n,&m);
124     while(n||m)
125     {
126         init();
127         int M=m;
128         while(M--)
129         {
130             int u,v;
131             scanf("%d%d",&u,&v);
132             addedge(u,v);
133             addedge(v,u);
134         }
135         solve();
136         scanf("%d%d",&n,&m);    
137     }
138     return 0;
139 }

 

 

以上是关于HDOJ4612双连通分量缩点+找树的直径的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4612 Warm up(双连通分量缩点+求树的直径)

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

HDU4612 Warm up

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

hdu4612 无向图中随意加入一条边后使桥的数量最少 / 无向图缩点+求树的直径

HDU 4612 Warm upBCC 树的直径