HDU4612+Tarjan缩点+BFS求树的直径

tarjan+缩点+树的直径
题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少。
先tarjan缩点,再在这棵树上求直径。加的边即是连接这条直径的两端。

  1 /*
  2 tarjan+缩点+树的直径
  3 题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少。
  4 先tarjan缩点,再在这棵树上求直径。加的边即是连接这条直径的两端。
  5 */
  6 #pragma comment(linker, "/STACK:1024000000,1024000000")  
  7 #include<stdio.h>
  8 #include<string.h>
  9 #include<stdlib.h>
 10 #include<stack>
 11 #include<algorithm>
 12 #include<iostream>
 13 #include<queue>
 14 #include<map>
 15 #include<math.h>
 16 using namespace std;
 17 typedef long long ll;
 18 //typedef __int64 int64;
 19 const int maxn = 300015;
 20 const int maxm = 2000015;
 21 const int inf = 0x7fffffff;
 22 const double pi=acos(-1.0);
 23 const double eps = 1e-8;
 24 struct Edge{
 25     int v,next;
 26 }edge[ maxm<<1 ],edgeTree[ maxm<<1 ];
 27 int cnt,cnt2,head[ maxn ],head2[ maxn ];
 28 int vis[ maxn ];
 29 int dfn[ maxn ];
 30 int low[ maxn ];
 31 int be[ maxn ];//缩点
 32 int sum;//the num of "缩点"
 33 int id;
 34 stack<int>sta;
 35 queue<int>q;
 36 int maxNode,maxs;//这棵树的直径maxs
 37 int dis[ maxn ];
 38 map<int,int>mp;
 39 void init(){
 40     cnt = cnt2 = 0;
 41     id = 0;
 42     sum = 0;
 43     //mp.clear();
 44     memset( head,-1,sizeof( head ) );
 45     memset( head2,-1,sizeof( head2 ) );
 46     memset( dfn,-1,sizeof( dfn ) );
 47     memset( vis,-1,sizeof( vis ) );
 48     memset( low,-1,sizeof( low ) );
 49     while( !sta.empty() )
 50         sta.pop();
 51 }
 52 void addedge( int a,int b ){
 53     edge[ cnt ].v = b;
 54     edge[ cnt ].next = head[ a ];
 55     head[ a ] = cnt++;
 56 }
 57 void addedge2( int a,int b ){
 58     edgeTree[ cnt2 ].v = b;
 59     edgeTree[ cnt2 ].next = head2[ a ];
 60     head2[ a ] = cnt2++;
 61 }
 62 
 63 void tarjan( int u,int Link ){
 64     dfn[ u ] = low[ u ] = id++;
 65     vis[ u ] = 1;
 66     sta.push( u );
 67     int cc = 0;
 68     for( int i=head[u];i!=-1;i=edge[i].next ){
 69         int v = edge[ i ].v;
 70         if( dfn[ v ]==-1 ){
 71             tarjan( v,u );
 72             low[ u ] = min( low[ u ],low[ v ] );
 73         }
 74         else if( Link==v ){
 75             if( cc ) low[ u ] = min( low[ u ],dfn[ v ] );
 76             cc++;
 77         } 
 78         else if( vis[ v ]==1 ){
 79             low[ u ] = min( low[ u ],dfn[ v ] );
 80         }
 81     }
 82     if( dfn[u]==low[u] ){
 83         sum++;
 84         int tt;
 85         while( 1 ){
 86             tt = sta.top();
 87             sta.pop();
 88             vis[ tt ] = 0;
 89             be[ tt ] = sum;
 90             if( tt==u ) break;
 91         }
 92     }
 93 }
 94 void buildTree( int n ){
 95     for( int i=1;i<=n;i++ ){
 96         for( int j=head[ i ];j!=-1;j=edge[ j ].next ){
 97             if( be[i]!=be[edge[j].v] ){
 98                 addedge2( be[i],be[edge[j].v] );
 99             }
100         }
101     }
102 }
103 void bfs( int s,int n ){
104     memset( vis,0,sizeof( vis ) );
105     vis[ s ] = 1;
106     while( !q.empty() )
107         q.pop();
108     q.push( s );
109     dis[ s ] = 0;
110     maxs = 0;
111     while( !q.empty() ){
112         int cur = q.front();
113         q.pop();
114         if( dis[ cur ]>=maxs ){
115             maxs = dis[ cur ];
116             maxNode = cur;
117         }
118         for( int i=head2[ cur ];i!=-1;i=edgeTree[ i ].next ){
119             int v = edgeTree[ i ].v;
120             if( vis[ v ]==1 ) continue;
121             vis[ v ] = 1;
122             dis[ v ] = dis[ cur ]+1;
123             q.push( v );
124         }    
125     }
126     return ;
127 }
128 int dfs(int u,int p)  
129 {  
130     int max1=0,max2=0;  
131     for (int i=head2[u];i!=-1;i=edgeTree[i].next)  
132     {  
133         int v=edgeTree[i].v;  
134         if (v==p) continue;  
135         int tmp=dfs(v,u)+1;  
136         if (max1<tmp) max2=max1,max1=tmp;  
137         else if (max2<tmp) max2=tmp;  
138     }  
139     maxs=max(maxs,max1+max2);  
140     return max1;  
141 } //dfs求树的直径 ok
142 int main(){
143     int n,m;
144     while( scanf("%d%d",&n,&m)&&(n+m) ){
145         int a,b;
146         init();
147         while( m-- ){
148             scanf("%d%d",&a,&b);
149             if( a==b ) continue;
150             //if( mp[min(a,b)] == max(a,b) ) continue;
151             //mp[min(a,b)] = max(a,b);
152             //不能这样去重边???
153             addedge( a,b );
154             addedge( b,a );
155         }
156         for( int i=1;i<=n;i++ ){
157             if( dfn[i]==-1 ){
158                 tarjan( i,-1 );
159             }
160         }
161         buildTree( n );
162         bfs( 1,sum );
163         bfs( maxNode,sum );
164         //printf("sum=%d, maxs=%d
",sum,maxs);
165         //maxs = 0;
166         //dfs( 1,-1 );
167         printf("%d
",sum-1-maxs);
168     }
169     return 0;
170 }
View Code
keep moving...
原文地址:https://www.cnblogs.com/xxx0624/p/3251907.html