题目链接:
http://acm.split.hdu.edu.cn/showproblem.php?pid=1269
题目大意:
所有城堡之间是否互达。
题目思路:
那么这个题目就是求解强连通分量是否为 1(强连通分量为1代表点点之间互达)
这个题目包括n=1 m=0的情况!!!被坑死。
代码要注意变量之间的初始化,wa到爆炸。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
vector<int>v[maxn];//邻接表
stack<int>s;
int dfn[maxn],low[maxn],tot,ans=maxn,ins[maxn];
int c_cnt;//统计强连通分量的个数
//dfn是否为0可以判断点是否访问过,ins数组用来判断点是否在栈中
//dfn数组表示顶点dfs的时间戳,low[]为u能够追溯到的最早的栈中顶点的次序号
int n,m;
int readin()
{
int x,y;
tot=0; //
c_cnt=0;
ans=maxn;//初始化
fill(ins,ins+maxn,0);
fill(dfn,dfn+maxn,0);
fill(low,low+maxn,0);
scanf("%d%d",&n,&m);
if(n==0&&m==0) return 0;
for(int i=1;i<=n;i++) v[i].clear();
while(!s.empty()) s.pop();
for(int i=1;i<=m;i++){
int u,vv;
scanf("%d%d",&u,&vv);
v[u].push_back(vv);
}
return 1;
}
void tarjan(int x)
{
low[x]=dfn[x]=++tot;//
s.push(x);ins[x]=1;
for(int i=0;i<v[x].size();i++){
int p=v[x][i];
if(!dfn[p]){//判断点是否被访问过
tarjan(p);
low[x]=min(low[x],low[p]);
}
else if(ins[p]) low[x]=min(low[x],dfn[p]);//判断点是否在栈中
}
if(low[x]==dfn[x]){//dfs到叶子节点,开始判断,如果==就到达了某个强联通分量的根节点,dfs回溯到了这个点
c_cnt++;
int cnt=0;
while(1){//得出相关的强联通分量
int now=s.top();
s.pop();
ins[x]=0;//出栈visit置0
cnt++;
if(now==x) break;//通过栈找到那个点
}
if(cnt>1) ans=min(ans,cnt);
}
}
int main()
{
while(readin()){
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i);
}
}
if(c_cnt==1) printf("Yes\n");
else printf("No\n");
}
}