码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-05-14 21:37:30      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:new   结构体   ges   sample   from   name   缩点   scanf   memset   

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】【双连通分量缩点+找树的直径】

标签:new   结构体   ges   sample   from   name   缩点   scanf   memset   

原文地址:https://www.cnblogs.com/MekakuCityActor/p/9038071.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!