POJ 2762
题目链接:
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=12633
题意:
给一个有向图,问两个点之间是否可达(能从一个点到另一个点就行)
思路:
强连通后缩点,然后判断它是不是链。
判断链的方法有很多,数据也比较水,丑陋的姿势如我能过。
源码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <iostream>
#include <stack>
#include <vector>
#include <queue>
using namespace std;
const int MAXN = 1e3 + 5;
vector<int>lin[MAXN], G[MAXN];
int vis[MAXN];
stack<int>S;
int n, m;
int sccno[MAXN], scc_cnt;
int in[MAXN];
int lv[MAXN][MAXN];
void dfs1(int u)
{
if(vis[u])
return;
vis[u] = 1;
for(int i = 0 ; i < (int)lin[u].size() ; i++){
int v = lin[u][i];
if(vis[v]) continue;
dfs1(v);
}
S.push(u);
}
void dfs2(int u)
{
if(sccno[u]) return;
sccno[u] = scc_cnt;
for(int i = 0 ; i < (int)G[u].size() ; i++){
int v = G[u][i];
if(sccno[v]) continue;
dfs2(v);
}
}
void kosaraju()
{
while(!S.empty()) S.pop();
memset(vis, 0, sizeof(vis));
for(int i = 1 ; i <= n ; i++)
if(vis[i] == 0) dfs1(i);
memset(sccno, 0, sizeof(sccno));
scc_cnt = 0;
while(!S.empty()){
int org = S.top(); S.pop();
if(sccno[org] == 0) scc_cnt++, dfs2(org);
}
}
bool check()
{
int ss = 0;
int u = -1;
for(int i = 1 ; i <= scc_cnt ; i++){
if(in[i] == 0){
// printf("i = %d\n")
if(u == -1) u = i;
else return false;
}
}
ss++;
// printf("scc_cnt = %d\n", scc_cnt);
// printf("u = %d\n", u);
// if(u == -1) return false;
while(vis[u] == 0){
vis[u] = 1;
int v = -1;
for(int i = 1 ; i <= scc_cnt ; i++){
if(lv[u][i]) in[i]--;
if(in[i] == 0 && vis[i] == 0){
if(v == -1) v = i;
else return false;
}
}
if(v == -1)
break;
ss++;
u = v;
}
if(ss == scc_cnt)
return true;
return false;
}
int main()
{
int t;
scanf("%d", &t);
while(t--){
scanf("%d%d", &n, &m);
for(int i = 1 ; i <= n ; i++)
lin[i].clear(), G[i].clear();
int u, v;
for(int i = 1 ; i <= m ; i++){
scanf("%d%d", &u, &v);
lin[u].push_back(v);
G[v].push_back(u);
}
kosaraju();
memset(lv, 0, sizeof(lv));
memset(in, 0, sizeof(in));
for(int i = 1 ; i <= n ; i++){
for(int j = 0 ; j < (int)lin[i].size() ; j++){
int u = i, v = lin[i][j];
if(sccno[u] != sccno[v] && lv[sccno[u]][sccno[v]] == 0){
lv[sccno[u]][sccno[v]] = 1;
in[sccno[v]]++;
}
}
}
// printf("scc_cnt = %d\n", scc_cnt);
int ok = 1;
memset(vis, 0, sizeof(vis));
ok = check();
if(!ok)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}