您的位置:首页 > 其它

zoj 2588 Burning Bridges

2012-02-06 12:26 471 查看


有向图强连通分量的Tarjan算法:http://www.byvoid.com/blog/scc-tarjan/

/*
zoj 2588    求割边
Tarjan算法。第一次写tarjan,完全学习别人写的。
注意点:
1.必须变成有向图存储,对于一条无向边,从一个方向访问过,则另一个方向不能访问。
2.因为两点之间可能有多条边,重边必定不是割边,需标记。
3.临界表存储。
*/
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#define N 10005
#define M 1000005
using namespace std;
int DFN
,LOW
,head[M],bridge[M],nbridge,k,num;
struct way
{
int next,id,v,tag;
}w[M];

void inint()
{
int i;
k=1;    nbridge=0;  num=1;
memset( head,0,sizeof(head) );
memset( DFN,0,sizeof(DFN) );
memset( LOW,0,sizeof(LOW) );
memset( bridge,0,sizeof(bridge) );
}

void addedge( int a,int b,int id )
{
int i;
for( i=head[a];i;i=w[i].next )
if( w[i].v==b ) break;
if(i)
{
w[i].tag=1;
return;
}
w[k].next=head[a];
w[k].id=id;
w[k].tag=0;
w[k].v=b;
head[a]=k;  k++;
}

void tarjan( int sta,int father )
{
int i,v;
DFN[sta]=LOW[sta]=++num;
for( i=head[sta];i;i=w[i].next )
{
v=w[i].v;
if( !DFN[v] )
{
tarjan( v,sta );
LOW[sta]=min( LOW[sta],LOW[v] );
if( DFN[sta]<LOW[v] && !w[i].tag )
bridge[nbridge++]=w[i].id;
}
else if( v!=father ) LOW[sta]=min( LOW[sta],DFN[v] );
}
}

int main()
{
int T,m,n,i;
int a,b;
scanf( "%d",&T );
while( T-- )
{
inint();
scanf( "%d%d",&n,&m );
for( i=0;i<m;i++ )
{
scanf( "%d%d",&a,&b );
addedge( a,b,i+1 );
addedge( b,a,i+1 );
}
tarjan( 1,-1 );
printf("%d\n",nbridge);
if(nbridge)
{
sort( bridge,bridge+nbridge );
for(i=0;i<nbridge-1;i++)
printf("%d ",bridge[i]);
printf("%d\n",bridge[nbridge-1]);
}
if(T) printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: