您的位置:首页 > 其它

图论强连通专题:POJ2762

2014-05-02 12:39 387 查看
题目描述:

给出图中一些点的连通关系,判断任意图中两个点是否能从u到v或者v到u。

大致思路:

思路还是先用强连通缩点,之后对于这个图进行拓扑排序,如果在排序过程中出现并列搜索的点了,也就是说这个子图中有多个起点,也就是说一定存在(u,v)不能u到v或者v到u。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

const int maxn = 1000 + 10;
bool g[maxn][maxn];
vector<int> gg[maxn];
vector<int> G[maxn];
vector<int> rG[maxn];
vector<int> vs;
bool used[maxn];
int n,m;
int cmp[maxn];
bool vis[maxn];
int v_in[maxn];
queue<int> s;

void add_edge(int from, int to) {
G[from].push_back(to);
rG[to].push_back(from);
}

void dfs(int v) {
used[v] = true;
for (int i = 0; i < G[v].size(); i++) {
if (!used[G[v][i]]) dfs(G[v][i]);
}
vs.push_back(v);
}

void rdfs(int v, int k) {
used[v] = true;
cmp[v] = k;
for (int i = 0; i < rG[v].size(); i++) {
if (!used[rG[v][i]]) rdfs(rG[v][i],k);
}
}

int scc() {
memset(used,0,sizeof(used));
vs.clear();
for (int i = 1; i <= n; i++) {
if (!used[i]) dfs(i);
}
memset(used,0,sizeof(used));
int k = 0;
for (int i = vs.size() - 1; i >=0; i--) {
if (!used[vs[i]]) rdfs(vs[i],k++);
}
return k;
}

bool top_sort(int n) {
if (n == 1) return true;
bool f = true;
for (int i = 0; i < n; i++)
if (!v_in[i] && f) {
s.push(i);
f = false;
}
else if (!v_in[i]) return false;
while (!s.empty()) {
int u = s.front();s.pop();
f = true;
for (int i = 0; i < gg[u].size(); i++) {
v_in[gg[u][i]]--;
if (!v_in[gg[u][i]] && f) {
s.push(gg[u][i]);
f = false;
}
else if (!v_in[gg[u][i]]) return false;
}
}
return true;
}

int main() {
int t;
cin>>t;
while (t--) {
cin>>n>>m;
while (!s.empty()) s.pop();
for (int i = 0; i <= n; i++) {
G[i].clear();
rG[i].clear();
gg[i].clear();
}
for (int i = 0; i < m; i++) {
int a,b;
scanf("%d%d",&a,&b);
add_edge(a,b);
}
int nN = scc();
memset(g,0,sizeof(g));
memset(v_in,0,sizeof(v_in));
for (int i = 1; i <= n; i++) {
for (int j = 0; j < G[i].size(); j++) {
if (cmp[i] != cmp[G[i][j]] && !g[cmp[i]][cmp[G[i][j]]]) {
g[cmp[i]][cmp[G[i][j]]] = true;
v_in[cmp[G[i][j]]] ++;
gg[cmp[i]].push_back(cmp[G[i][j]]);
}
}
}
memset(vis,0,sizeof(vis));
if (top_sort(nN)) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM 图论 强连通