pku 2553 The Bottom of a Graph(tarjan缩点)

http://poj.org/problem?id=2553

题意才开始理解错了一位G中的任意一点都能到达v且v也能达到该点时v才属于bottom;如果这样最后出度为0的比为一个了,而且整个图都要缩为一点了。

其实题意是说w属于G如果v->w ==>(推出)w->v则v属于bottom。先缩点,然后统计出度为0的点,然后输出所有出度为0的点包含的点。如果出度不为0,那么v->w退不出w->v

这里的DAG比存在出度为0的点。。。所以都骂出题的二逼啊。。。

View Code
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include <iostream>
#define maxn 10017
using namespace std;
int low[maxn],dfn[maxn],val[maxn],out[maxn];
bool instack[maxn],hash[maxn];
int belong[maxn];
int bcnt,index;
int n,m;
vector<int>g[maxn];
stack<int>s;
void init()
{
for (int i = 0; i < maxn; ++i)
{
g[i].clear();
low[i] = dfn[i] = belong[i] = val[i] = out[i] = 0;
instack[i] = hash[i] = false;
}
index = bcnt =0;
}
void tarjan(int i)
{
int j,k;
low[i] = dfn[i] = ++index;
s.push(i);
instack[i] = true;
for (k = 0; k < g[i].size(); ++k)
{
j = g[i][k];
if (!dfn[j])
{
tarjan(j);
low[i] = min(low[i],low[j]);
}
else if (instack[j])
{
low[i] = min(low[i],dfn[j]);
}
}
if(low[i] == dfn[i])
{
bcnt++;
do
{
j = s.top();
s.pop();
instack[j] = false;
belong[j] = bcnt;
} while (j != i);
}
}
void solve()
{
int i,j;
for (i = 1; i <= n; ++i)
{
if (!dfn[i]) tarjan(i);
}
for (i = 1; i <= n; ++i)
{
for (j = 0; j < g[i].size(); ++j)
{
int k = g[i][j];
if (belong[i] != belong[k])
out[belong[i]]++;
}
}
int flag[maxn] = {0};//注意输出的处理
for (i = 1; i <= bcnt; ++i)
{
if (!out[i]) flag[i] = 1;
}
int f = 0;
for (i = 1; i <= n; ++i)
{
if (flag[belong[i]])
{
if(f == 0)
{
printf("%d",i);
f = 1;
}
else
printf(" %d",i);
}
}
printf("\n");
}
int main()
{
//freopen("d.txt","r",stdin);
int x,y,i;
while (cin>>n)
{
if (!n) break;
cin>>m;
init();
for (i = 1; i <= m; ++i)
{
cin>>x>>y;
g[x].push_back(y);
}
solve();
}
return 0;
}



你可能感兴趣的:(Graph)