题目链接:http://poj.org/problem?id=2762
给定顶点和边的关系,问是否对于任意的顶点x和y,总存在x到y的路径或y到x的路径,一开始看成和的关系,判断只有一个连通分量。
如果是或的话,就是对于缩点后的图看看能不能找到一条路径贯穿所有的点,用拓扑排序更新出到达每个顶点最多能有几个顶点。然后如果顶点个数=强连通分量数,那么就是符合题意的。
附上测试数据和代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 1002;
const int maxm = 6005;
int n, m;
int head[maxn];
struct E {
int to;
int next;
} edge[maxm];
int dfn[maxn];
int low[maxn];
bool instack[maxn];
int stap[maxn];
int belong[maxn];
vector<int> G[maxn];
int indeg[maxn];
int index, cur, cnt, eid;
int dis[maxn];
void addedge(int from, int to) {
edge[eid].to = to;
edge[eid].next = head[from];
head[from] = eid ++;
}
void targan(int v) {
dfn[v] = low[v] = ++index;
instack[v] = true;
stap[++cur] = v;
for (int i = head[v]; ~i; i = edge[i].next) {
int to = edge[i].to;
if(!dfn[to]) {
targan(to);
low[v] = min(low[v], low[to]);
} else if(instack[to]) {
low[v] = min(low[v], dfn[to]);
}
}
if(dfn[v] == low[v]) {
cnt ++;
int j;
do {
j = stap[cur--];
instack[j] = false;
belong[j] = cnt;
} while (j != v);
}
}
void suo() {
for(int i = 1; i <= cnt; i ++) {
G[i].clear();
indeg[i] = 0;
}
for (int i = 1; i <= n; i ++) {
for (int j = head[i]; ~j; j = edge[j].next) {
if(belong[i] != belong[edge[j].to]) {
G[belong[i]].push_back(belong[edge[j].to]);
indeg[belong[edge[j].to]] ++;
}
}
}
}
bool topo() {
queue<int> que;
for (int i = 1; i <= cnt; i ++) {
if(indeg[i] == 0) {
que.push(i);
dis[i] = 1;
}
else {
dis[i] = 0;
}
}
while(!que.empty()) {
int cur = que.front();
que.pop();
for(int i = 0; i < G[cur].size(); i ++) {
int to = G[cur][i];
dis[to] = max(dis[to], dis[cur] + 1);
indeg[to] --;
if(indeg[to] == 0) {
que.push(to);
}
}
}
for(int i = 1; i <= cnt; i ++) {
if(dis[i] == cnt) {
return true;
}
}
return false;
}
int main() {
int x, y, t;
// freopen("1.in", "r", stdin);
scanf("%d", &t);
while (t --) {
scanf("%d%d",&n, &m);
memset(head, -1, sizeof(head));
memset(dfn, 0, sizeof(dfn));
memset(instack, false, sizeof(instack));
eid = 0;
for (int i = 0; i < m; i ++) {
scanf ("%d%d", &x, &y);
addedge(x, y);
}
cur = index = cnt = 0;
for (int i = 1; i <= n; i++) {
if(!dfn[i]) {
targan(i);
}
}
suo();
if(topo()) {
printf("Yes\n");
}
else {
printf("No\n");
}
}
return 0;
}
/*
11
8 10
1 5
6 3
2 7
7 8
3 6
8 2
2 1
4 6
7 3
6 5
5 8
1 2
2 3
3 4
1 3
1 4
2 4
4 5
5 4
6 10
6 3
2 5
4 6
3 6
2 6
6 1
1 5
3 2
4 1
5 3
7 8
1 2
3 1
3 2
2 4
4 7
4 5
5 6
6 4
3 3
1 2
2 3
3 1
5 5
1 2
2 3
3 1
3 4
4 5
4 4
1 2
2 3
3 1
4 3
4 4
1 2
1 3
2 4
3 4
3 3
1 2
2 1
3 1
4 4
1 2
1 3
2 4
3 4
4 5
1 2
2 3
2 4
1 3
1 4
No
Yes
Yes
Yes
Yes
Yes
Yes
No
Yes
No
No
*/