题目地址:http://acm.pku.edu.cn/JudgeOnline/problem?id=2762
这题实际上是判断是否是弱连通的,所以首先强连通,然后缩点,对缩点形成的图最多只能有一个入度为0的点,
如果有多个入度为0的点,则这两个连通分量肯定是不连通的。
缩点后形成的图形是一棵树,入度为0的点是这颗树的根,这棵树只能是单链,不能有分叉,如果有分叉,则这些
分叉之间是不可达的,所以就对这棵树进行DFS,如果是单链则是YES。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int n,m;
int f[1010];
int times;
bool flag;
int vBlock[1010];
bool visited[1010];
int in[1010];
vector <int> map1[1010];
vector <int> map2[1010];
vector <int> map3[1010];
int numCnt;
void dfs1(int v)
{
visited[v] = true;
for (int i=0;i<map1[v].size();i++)
{
int cur = map1[v][i];
if (!visited[cur])
{
dfs1(cur);
}
}
f[times++] = v;
}
void dfs2(int v,int id)
{
vBlock[v] = id;
visited[v] = true;
for (int i=0;i<map2[v].size();i++)
{
int cur = map2[v][i];
if (!visited[cur])
{
dfs2(cur,id);
}
}
}
void dfs(int v)
{
numCnt++;
int len = map3[v].size();
if (len>1)
{
flag = false;
return;
}
else if (len==1)
{
dfs(map3[v][0]);
}
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
memset(visited,false,sizeof(visited));
times = 0;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
map1[i].clear();
map2[i].clear();
map3[i].clear();
}
for (int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
map1[a].push_back(b);
map2[b].push_back(a);
}
for (int i=1;i<=n;i++)
{
if (!visited[i])
{
dfs1(i);
}
}
memset(visited,false,sizeof(visited));
memset(vBlock,0,sizeof(vBlock));
int block = 0;
for (int i=times-1;i>=0;i--)
{
if (!visited[f[i]])
{
dfs2(f[i],++block);
}
}
// printf("Block %d\n",block);
memset(in,0,sizeof(in));
for (int i=1;i<=n;i++)
for (int j=0;j<map1[i].size();j++)
{
int cur = map1[i][j];
if (vBlock[i]!=vBlock[cur])
{
map3[vBlock[i]].push_back(vBlock[cur]);
in[vBlock[cur]]++;
}
}
int cnt =0;
int fst;
for (int i=1;i<=block;i++)
{
if (in[i]==0)
{
cnt++;
fst = i;
}
}
if (cnt>1)
{
printf("No\n");
}
else
{
flag = true;
numCnt = 0;
dfs(fst);
if (flag&&numCnt==block)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
}
return 0;
}
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int n,m;
int f[1010];
int times;
bool flag;
int vBlock[1010];
bool visited[1010];
int in[1010];
vector <int> map1[1010];
vector <int> map2[1010];
vector <int> map3[1010];
int numCnt;
void dfs1(int v)
{
visited[v] = true;
for (int i=0;i<map1[v].size();i++)
{
int cur = map1[v][i];
if (!visited[cur])
{
dfs1(cur);
}
}
f[times++] = v;
}
void dfs2(int v,int id)
{
vBlock[v] = id;
visited[v] = true;
for (int i=0;i<map2[v].size();i++)
{
int cur = map2[v][i];
if (!visited[cur])
{
dfs2(cur,id);
}
}
}
void dfs(int v)
{
numCnt++;
int len = map3[v].size();
if (len>1)
{
flag = false;
return;
}
else if (len==1)
{
dfs(map3[v][0]);
}
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
memset(visited,false,sizeof(visited));
times = 0;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
map1[i].clear();
map2[i].clear();
map3[i].clear();
}
for (int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
map1[a].push_back(b);
map2[b].push_back(a);
}
for (int i=1;i<=n;i++)
{
if (!visited[i])
{
dfs1(i);
}
}
memset(visited,false,sizeof(visited));
memset(vBlock,0,sizeof(vBlock));
int block = 0;
for (int i=times-1;i>=0;i--)
{
if (!visited[f[i]])
{
dfs2(f[i],++block);
}
}
// printf("Block %d\n",block);
memset(in,0,sizeof(in));
for (int i=1;i<=n;i++)
for (int j=0;j<map1[i].size();j++)
{
int cur = map1[i][j];
if (vBlock[i]!=vBlock[cur])
{
map3[vBlock[i]].push_back(vBlock[cur]);
in[vBlock[cur]]++;
}
}
int cnt =0;
int fst;
for (int i=1;i<=block;i++)
{
if (in[i]==0)
{
cnt++;
fst = i;
}
}
if (cnt>1)
{
printf("No\n");
}
else
{
flag = true;
numCnt = 0;
dfs(fst);
if (flag&&numCnt==block)
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
}
return 0;
}