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\n",sum,maxs); 165 //maxs = 0; 166 //dfs( 1,-1 ); 167 printf("%d\n",sum-1-maxs); 168 } 169 return 0; 170 }
keep moving...