ZOJ2588 Burning Bridges(割边模板)

题目要输出一个无向图的所有割边。用Tarjan算法:

一遍DFS,构造出一颗深度优先生成树,在原无向图中边分成了两种:树边(生成树上的边)和反祖边(非生成树上的边)。

顺便求出每个结点的DFS序dfn[u] 和 每个结点能沿着它和它的儿子的返祖边达到的结点最小的DFS序low[u]

一条边(u,v)是割边当且仅当——

  • low[v]>dfn[u]

注意具体实现时,无向图的边在邻接表中有正反两条边,那么如果一条边是树边了,另一条边不应该是反祖边,要忽略。

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXM 222222
#define MAXN 11111
struct Edge{
int v,next;
bool tag;
}edge[MAXM];
int NE,head[MAXN];
void addEdge(int u,int v){
edge[NE].v=v; edge[NE].next=head[u]; edge[NE].tag=;
head[u]=NE++;
}
int dn,dfn[MAXN],low[MAXN],res[MAXM],resn;
void dfs(int u){
dfn[u]=low[u]=++dn;
for(int i=head[u]; i!=-; i=edge[i].next){
if(edge[i].tag) continue;
int v=edge[i].v;
if(dfn[v]){
low[u]=min(low[u],dfn[v]);
continue;
}
edge[i].tag=edge[i^].tag=;
dfs(v);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]) res[resn++]=(i>>)+;
}
}
int main(){
int t,n,m,a,b;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
NE=;
memset(head,-,sizeof(head));
while(m--){
scanf("%d%d",&a,&b);
addEdge(a,b); addEdge(b,a);
}
resn=dn=;
memset(dfn,,sizeof(dfn));
dfs();
printf("%d\n",resn);
sort(res,res+resn);
for(int i=; i<resn; ++i){
if(i) putchar(' ');
printf("%d",res[i]);
}
if(resn) putchar('\n');
if(t) putchar('\n');
}
return ;
}
上一篇:java设计模式--事件监听器模式(观察者模式)


下一篇:PL/0编译器(java version)–Praser.java