您的位置:首页 > 其它

POJ 1236 Network of Schools(强连通分量)

2017-04-13 19:41 381 查看

题目分析

这道题首先强连通处理 ,然后求缩点之后的每个点的入度和出度。第一个肯定就是输出入度为0的点,第二个就是输出入度和出度的最大值,因此要保证一个图强连通,那么这个图的每个点肯定既有出去的边也有进来的边。注意当整个图相连通的时候的时候要特判。

#include <stack>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1005;

int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
vector <int> G[maxn];
stack <int> S;
int in[maxn], out[maxn];

int dfs(int u){
pre[u] = lowlink[u] = ++dfs_clock;
S.push(u);
for(unsigned int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if(!pre[v]){
dfs(v);
lowlink[u] = min(lowlink[u], lowlink[v]);
}
else if(!sccno[v]){
lowlink[u] = min(lowlink[u], pre[v]);
}
}
if(lowlink[u] == pre[u]){
scc_cnt++;
for(;;){
int x = S.top(); S.pop();
sccno[x] = scc_cnt;
if(x == u) break;
}
}
return lowlink[u];
}

void find_scc(int n){
dfs_clock = scc_cnt = 0;
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
memset(pre, 0, sizeof(pre));
memset(lowlink, 0, sizeof(lowlink));
memset(sccno, 0, sizeof(sccno));
for(int i = 0; i < n; i++)
if(!pre[i]) dfs(i);
}

int main(){
int n;
while(scanf("%d", &n) != EOF){
int v;
for(int u = 0; u < n; u++){
while(scanf("%d", &v) && v){
v--;
G[u].push_back(v);
}
}
find_scc(n);
for(int u = 0; u < n; u++){
for(unsigned int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if(sccno[v] != sccno[u]) in[sccno[v]] = out[sccno[u]] = 1;
}
}
int a = 0, b = 0;
for(int i = 1; i <= scc_cnt; i++){
if(!in[i]) a++;
if(!out[i]) b++;
}
if(scc_cnt == 1) printf("1\n0\n");
else printf("%d\n%d\n", a, max(a,b));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: