您的位置:首页 > 其它

hdu1269 迷宫城堡 (强连通模板)(有向图)

2015-05-01 20:59 387 查看
///题意当强连通分量为1的时候输出Yes否者输出No。 两两可达
# include<stdio.h>
# include<algorithm>
# include<stack>
# include<vector>
# include<string.h>
using namespace std;
# define MAXN 10005 ///题目中可能的最大点数
# define MAXM 100005 ///边数
struct Edge
{
int v,next;
} edge[MAXM]; ///边结点数组      边
int first[MAXN],Stack[MAXN],DFN[MAXN],Low[MAXN],Belong[MAXM];///边
///first[]头结点数组  stack[]为栈  DFN[]为深度优先搜索次序数组
///Belong[]为每个结点所对应的强连通分量标号数组
///Low[u]为u结点的子树结点所能追溯到的最早栈中的标记数组
int instack[MAXN];///是否在栈中的标记数组
int n,m,cnt,scnt,top,tot;
void init()
{
cnt=0;
scnt=top=tot=0;///初始化连通分量标号,栈顶指针,次序计数器为0
memset(first,-1,sizeof(first));
memset(DFN,0,sizeof(DFN));///结点搜素的次序编号数组为0,同时可以当作是否访问的数组使用
}
void read_graph(int u,int v)///构建邻接表
{
edge[tot].v=v;
edge[tot].next=first[u];
first[u]=tot++;
}
void Tarjan(int v)
{
int min,t;
DFN[v]=Low[v]=++tot; ///cnt为时间戳
instack[v]=1;///标记在栈中
Stack[top++]=v;///入栈
for(int e=first[v];e!=-1;e=edge[e].next)
{///枚举每一条边
int j=edge[e].v; ///v所邻接的边
if(!DFN[j])///未被访问
{
Tarjan(j);///继续往下找
if(Low[v]>Low[j])
Low[v]=Low[j];///更新结点v到所能到达的最小次数层
}
else if(instack[j]&&DFN[j]<Low[v])
{//如果j结点在栈内
Low[v]=DFN[j];

}
}
if(DFN[v]==Low[v])
{///如果结点v是强连通分量的根
scnt++;///连通分量+1
do
{
t=Stack[--top];///退栈
instack[t]=0;///标记不在栈中
Belong[t]=scnt;///出栈结点t属于cnt标号的强连通分量
}while(t!=v);///知道将v从栈中退出

}
}
void slove()
{
for(int i=1;i<=n;i++)///枚举每个结点,搜索连通分量
if(!DFN[i])///未被访问
Tarjan(i);///则找i结点的连通分量
}
int main()
{
while(~scanf("%d%d",&n,&m),n+m)
{
init();
for(int i=1; i<=m; i++)
{
int a,b;
scanf("%d%d",&a,&b);
read_graph(a,b);
}
slove();///求强连通分量
if(scnt==1)///只有一个强连通分量,所以两两都可到达
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: