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

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

 /*
tarjan+缩点+树的直径
题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少。
先tarjan缩点,再在这棵树上求直径。加的边即是连接这条直径的两端。
*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stack>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
typedef long long ll;
//typedef __int64 int64;
const int maxn = ;
const int maxm = ;
const int inf = 0x7fffffff;
const double pi=acos(-1.0);
const double eps = 1e-;
struct Edge{
int v,next;
}edge[ maxm<< ],edgeTree[ maxm<< ];
int cnt,cnt2,head[ maxn ],head2[ maxn ];
int vis[ maxn ];
int dfn[ maxn ];
int low[ maxn ];
int be[ maxn ];//缩点
int sum;//the num of "缩点"
int id;
stack<int>sta;
queue<int>q;
int maxNode,maxs;//这棵树的直径maxs
int dis[ maxn ];
map<int,int>mp;
void init(){
cnt = cnt2 = ;
id = ;
sum = ;
//mp.clear();
memset( head,-,sizeof( head ) );
memset( head2,-,sizeof( head2 ) );
memset( dfn,-,sizeof( dfn ) );
memset( vis,-,sizeof( vis ) );
memset( low,-,sizeof( low ) );
while( !sta.empty() )
sta.pop();
}
void addedge( int a,int b ){
edge[ cnt ].v = b;
edge[ cnt ].next = head[ a ];
head[ a ] = cnt++;
}
void addedge2( int a,int b ){
edgeTree[ cnt2 ].v = b;
edgeTree[ cnt2 ].next = head2[ a ];
head2[ a ] = cnt2++;
} void tarjan( int u,int Link ){
dfn[ u ] = low[ u ] = id++;
vis[ u ] = ;
sta.push( u );
int cc = ;
for( int i=head[u];i!=-;i=edge[i].next ){
int v = edge[ i ].v;
if( dfn[ v ]==- ){
tarjan( v,u );
low[ u ] = min( low[ u ],low[ v ] );
}
else if( Link==v ){
if( cc ) low[ u ] = min( low[ u ],dfn[ v ] );
cc++;
}
else if( vis[ v ]== ){
low[ u ] = min( low[ u ],dfn[ v ] );
}
}
if( dfn[u]==low[u] ){
sum++;
int tt;
while( ){
tt = sta.top();
sta.pop();
vis[ tt ] = ;
be[ tt ] = sum;
if( tt==u ) break;
}
}
}
void buildTree( int n ){
for( int i=;i<=n;i++ ){
for( int j=head[ i ];j!=-;j=edge[ j ].next ){
if( be[i]!=be[edge[j].v] ){
addedge2( be[i],be[edge[j].v] );
}
}
}
}
void bfs( int s,int n ){
memset( vis,,sizeof( vis ) );
vis[ s ] = ;
while( !q.empty() )
q.pop();
q.push( s );
dis[ s ] = ;
maxs = ;
while( !q.empty() ){
int cur = q.front();
q.pop();
if( dis[ cur ]>=maxs ){
maxs = dis[ cur ];
maxNode = cur;
}
for( int i=head2[ cur ];i!=-;i=edgeTree[ i ].next ){
int v = edgeTree[ i ].v;
if( vis[ v ]== ) continue;
vis[ v ] = ;
dis[ v ] = dis[ cur ]+;
q.push( v );
}
}
return ;
}
int dfs(int u,int p)
{
int max1=,max2=;
for (int i=head2[u];i!=-;i=edgeTree[i].next)
{
int v=edgeTree[i].v;
if (v==p) continue;
int tmp=dfs(v,u)+;
if (max1<tmp) max2=max1,max1=tmp;
else if (max2<tmp) max2=tmp;
}
maxs=max(maxs,max1+max2);
return max1;
} //dfs求树的直径 ok
int main(){
int n,m;
while( scanf("%d%d",&n,&m)&&(n+m) ){
int a,b;
init();
while( m-- ){
scanf("%d%d",&a,&b);
if( a==b ) continue;
//if( mp[min(a,b)] == max(a,b) ) continue;
//mp[min(a,b)] = max(a,b);
//不能这样去重边???
addedge( a,b );
addedge( b,a );
}
for( int i=;i<=n;i++ ){
if( dfn[i]==- ){
tarjan( i,- );
}
}
buildTree( n );
bfs( ,sum );
bfs( maxNode,sum );
//printf("sum=%d, maxs=%d\n",sum,maxs);
//maxs = 0;
//dfs( 1,-1 );
printf("%d\n",sum--maxs);
}
return ;
}
上一篇:PDF 补丁丁 0.4.2.1023 测试版发布:新增旋转页面功能


下一篇:架构设计 | 接口幂等性原则,防重复提交Token管理