您的位置:首页 > 其它

POJ 1236(tarjan+缩点)

2016-04-14 17:53 399 查看
把所有强连通分量各缩成一个点,重新建图,ans1 = 入度为0的点的个数 ans2 = max(入度为零的点的个数,出度为0的点的个数)

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
using namespace std;
const int maxn = 100 + 7;
int n, k = 0, newk = 0;
vector<int> G[maxn];
vector<int> newG[maxn];
int dfn[maxn], low[maxn], in[maxn];
int inq[maxn], outq[maxn];
int p[maxn];
stack<int> s;

void tarjan(int u) {
dfn[u] = low[u] = ++k;
s.push(u);
in[u] = 1;
for(int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if(in[v]) low[u] = min(low[u], dfn[v]);
}
int v;
if(low[u] == dfn[u]) {
int id = ++newk;
do {
v = s.top();
s.pop();
in[v] = 0;
p[v] = id;
} while(u != v);
}
}

void init() {
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(in, 0, sizeof(in));
memset(inq, 0, sizeof(inq));
memset(outq, 0, sizeof(outq));
k = 0, newk = 0;
for(int i = 1; i <= n; ++i) {
G[i].clear();
newG[i].clear();
}
while(!s.empty()) s.pop();
}

void makenewG() {
for(int i = 1; i <= n; ++i)
for(int j = 0; j < G[i].size(); ++j) {
int v = G[i][j];
if(p[i] != p[v])
newG[p[i]].push_back(p[v]);
}
}

int main() {
while(scanf("%d", &n) != EOF) {
for(int i = 1; i <= n; ++i) {
int u;
while(scanf("%d", &u) && u)
G[i].push_back(u);
}
for(int i = 1; i <= n; ++i)
if(!dfn[i]) tarjan(i);

makenewG();

int IN = 0, OUT = 0;
for(int i = 1; i <= newk; ++i) {
outq[i] = newG[i].size();
for(int j = 0; j < newG[i].size(); ++j) {
int v = newG[i][j];
inq[v]++;
}
}
for(int i = 1; i <= newk; ++i) {
if(inq[i] == 0) IN++;
if(outq[i] == 0) OUT++;
}
if(newk == 1) printf("1\n0\n");
else printf("%d\n%d\n", IN, max(IN, OUT));
}
return 0;
}

/**

3
2 0
3 0
1 0

**/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: