您的位置:首页 > 其它

poj2553 The Bottom of a Graph

2011-07-17 10:03 405 查看
题意一开始理解有点小问题,题目大意是说如果一个点v能够到达w并且w也能到v则w和v都称为一个sink,题目要求从大到小输出图中所有的sink点,可能有人会对第二组数据不太理解,看一下这个图



显然1有一条边连接到2,如果1是sink点则2也要能够走到1,显然2是sink点因为它没有指向任何点,由此可以看出,只要一个强连通分量没有指向任何点,那么这个分量中的全部点就都是sink点,那么也就是说,只需要输出全部强连通分量出度为0的情况就可以了,记得要排序

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
const int size = 11000;
vector <int> mapp[size], remapp[size];
vector <int>comp[size];
vector <int>sccindex[size];
map <int, int> mak;
bool visited[size];
int num[size];
int belg[size];
int counter;
int n ;
int edge[5*size][2]; //0记录出点,1记录入点
void init()
{
for (int i = 0; i <= n; i ++){
mapp[i].clear(), remapp[i].clear(), comp[i].clear(), sccindex[i].clear();
}
mak.clear();
}
void dfs1(int v)
{
visited[v] = true;
for (int i = 0; i < mapp[v].size(); i ++){
int t = mapp[v][i];
if (!visited[t]){
dfs1(t);
}
}
num[++counter]= v;
}
int kk;
void dfs2(int v)
{
visited[v] = true;
sccindex[kk].push_back(v);//记录第kk个强连通分量中的点
mak[v] = kk;//记录第kk个点属于第几个强连通分量
for (int i = 0; i < remapp[v].size(); i ++){
int t = remapp[v][i];
if (!visited[t]){
belg[t] = kk;
dfs2(t);
}
}

}

void scc()
{
counter = 0;
memset(visited, false, sizeof(visited));
for (int i = 1; i <= n; i ++){
if (!visited[i]){
dfs1(i);
}
}
// cout<<"counter: "<<counter<<endl;
memset(visited, false ,sizeof(visited));
kk = 0;
for (int i = counter; i >= 1; i --){
int k = num[i];
if (!visited[k]){
visited[k] = true;
++ kk;
dfs2(k);

}
}
}

void compress()
{
for (int i = 1; i <= n; i ++){
for (int j = 0; j < mapp[i].size(); j ++){
if (belg[mapp[i][j]] != belg[i]){
comp[belg[i]].push_back(belg[mapp[i][j]]);
}
}
}
}
int main()
{
//freopen("IN.txt", "r", stdin);
//freopen("OUT.txt", "w", stdout);
int m;
while (scanf("%d", &n) != EOF && n){
scanf("%d", &m);
init();
int t;
int a, b;
for (int i = 0; i < m; i ++){
scanf("%d%d", &a, &b);
edge[i][0] = a;
edge[i][1] = b;
mapp[a].push_back(b);
remapp[b].push_back(a);
}
scc();
compress();
int OUT[size] = {0};
for (int i = 0; i < m; i ++){
a = mak[edge[i][0]], b = mak[edge[i][1]];//a,b表示每个出点入点所在的强连通分量位置
if (a != b){
OUT[a] ++;
}
}
int ans[size];
int id= 0;
for (int i = 1; i <= kk; i ++){
if (!OUT[i]){
for (int j = 0; j < sccindex[i].size(); j ++){
ans[id ++] = sccindex[i][j];
}
}
}
sort(ans, ans+id);
for (int i = 0; i < id; i ++){
if (i)printf(" ");
printf("%d", ans[i]);
}
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: