题目:http://poj.org/problem?id=2762
题意:给出n个山洞,对于每个山洞,如果任意选择两点s,e,都满足s可以到达e或者e可以到达s,则输出Yes,否则输出No。
分析:实际上判断是否弱连通,所以首先强连通,然后缩点,对缩点形成的图最多只能有一个入度为0的点,如果有多个入度为
0的点,则这两个连通分量肯定是不连通的。缩点后形成的图形是一棵树,入度为0的点是这颗树的根,这棵树只能是单链,不
能有分叉,如果有分叉,则这些分叉之间是不可达的,所以就对这棵树进行DFS,如果是单链则是YES。
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int N = 10005;
struct Edge
{
int to;
Edge *next;
};
Edge *map1[N],*map2[N]; //分别保存原图和缩点后的图
int dfn[N],low[N],stack[N],belong[N],indeg[N];
int index,scc_num,top;
bool tmp[N];
int result[N];
void Tarjan(int u)
{
dfn[u] = low[u] = ++index;
stack[++top] = u;
tmp[u] = true;
for(Edge *p = map1[u]; p; p = p->next) //枚举每一条边
{
int v = p->to;
if(!dfn[v])
{
Tarjan(v); //dfs继续下找
low[u] = min(low[u],low[v]);
}
else if(tmp[v])
{
low[u] = min(low[u],dfn[v]);
}
}
if(low[u] == dfn[u]) //如果节点u是强连通分量的根
{
int t;
++scc_num; //强连通分量个数加1
do
{
t = stack[top--];
tmp[t] = false;
belong[t] = scc_num; //记录属于第几个强连通分量
}
while(t != u);
}
}
int Count(int n)
{
for(int i=1;i<=n;i++)
if(!dfn[i])
Tarjan(i);
return scc_num;
}
int Find() //在新图中找入度为0的点,如果只有一个就返回位置,否则返回0
{
int record;
int cnt = 0;
for(int i=1; i<=scc_num; i++)
{
if(indeg[i] == 0)
{
cnt++;
record = i;
}
}
if(cnt == 1) return record;
return 0;
}
bool TopSort()
{
int u,num = 0;
while(u = Find())
{
result[num++] = u;
indeg[u] = -1;
Edge *p = map2[u];
while(p)
{
indeg[p->to]--;
p = p->next;
}
}
if(num == scc_num) return true;
return false;
}
void Init()
{
index = 0;
top = 0;
scc_num = 0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(indeg,0,sizeof(indeg));
memset(tmp,false,sizeof(tmp));
memset(map1,NULL,sizeof(map1));
memset(map2,NULL,sizeof(map2));
memset(result,0,sizeof(result));
}
int main()
{
int T,m,n;
scanf("%d",&T);
while(T--)
{
Init();
scanf("%d%d",&n,&m);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
Edge *p = new Edge();
p->to = b;
p->next = map1[a];
map1[a] = p;
}
int cnt = Count(n);
if(cnt == 1)
{
puts("Yes");
continue;
}
for(int i=1;i<=n;i++)
{
Edge *p = map1[i];
while(p)
{
if(belong[i] != belong[p->to])
{
indeg[belong[p->to]]++;
Edge *q = new Edge();
q->to = belong[p->to];
q->next = map2[belong[i]];
map2[belong[i]] = q;
}
p = p->next;
}
}
bool flag = false;
int ans = 0;
for(int i=1;i<=cnt;i++)
{
if(indeg[i] == 0)
ans++;
}
if(ans > 1) flag = false;
else if(TopSort()) flag = true;
if(flag) puts("Yes");
else puts("No");
}
return 0;
}
标签:连通,int,memset,无向,POJ2762,dfn,Edge,sizeof,low From: https://blog.51cto.com/u_16146153/6388134