您的位置:首页 > 其它

poj2553 The Bottom of a Graph--Kosaraju算法 & 缩点 & 强连通分量

2016-09-10 14:38 423 查看
原题链接:http://poj.org/problem?id=2553

题意:n个点,m对点的关系,定义link点:一个点u所能到达的点,反过来都能到达u,那么点u就是link点。升序输出所有的link点。

分析:强连通缩点后,找到出度为0的即可,具体为什么,看 给的两个实例。

#define _CRT_SECURE_NO_DEPRECATE

#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
#include<algorithm>
#define INF 99999999
using namespace std;

int n, m;
int cnt;
int index[5005];
bool mark[5005];
int out[5005];
vector<int> s;
vector<int> c[5005];
vector<int> g[5005];
vector<int> rg[5005];

void dfs1(int x)
{
mark[x] = 1;
for (int i = 0; i < g[x].size(); i++)
if (!mark[g[x][i]])
dfs1(g[x][i]);
s.push_back(x);
}

void dfs2(int x)
{
index[x] = cnt;
c[cnt].push_back(x);
mark[x] = 1;
for (int i = 0; i < rg[x].size(); i++)
if (!mark[rg[x][i]])
dfs2(rg[x][i]);
}

void Kosaraju()
{
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < g[i].size(); j++)
{
int t = g[i][j];
if (index[t] != index[i])
out[index[i]]++;
}
}

vector<int> t;
for (int i = 1; i <= cnt; i++)
if (out[i] == 0)
for (int j = 0; j < c[i].size(); j++)
t.push_back(c[i][j]);

sort(t.begin(), t.end());

for (int i = 0; i < t.size() - 1; i++)
printf("%d ", t[i]);
if (t.size())
printf("%d", t[t.size() - 1]);
printf("\n");
}

int main()
{
int u, v;
while (scanf("%d", &n) && n)
{
scanf("%d", &m);

//init
for (int i = 1; i <= n; i++)
{
g[i].clear();
rg[i].clear();
s.clear();
c[i].clear();
memset(mark, 0, sizeof(mark));
memset(index, 0, sizeof(index));
memset(out, 0, sizeof(out));
}

//scanf
for (int i = 0; i < m; i++)
{
scanf("%d%d", &u, &v);
g[u].push_back(v);
rg[v].push_back(u);
}

for (int i = 1; i <= n; i++)
if (!mark[i])
dfs1(i);
memset(mark, 0, sizeof(mark));
cnt = 0;
for (int i = s.size() - 1; i >= 0; i--)
{
if (!mark[s[i]])
{
cnt++;
dfs2(s[i]);
}
}

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