来源:http://poj.org/problem?id=2553
题意:题目新给了一个定义,在一个图中,若从点v能够到达点w,且从w能够到达点v,则称v为sink。让输出一个图中sink的序号,按升序输出。
思路:首先根据定义,易知,因为是有向图,所以一个孤立的强联通分量里面的点都是sink,这点很容易理解,因为强联通分量里面的点都是互达的。而且该强联通分量是孤立的,也就是说,该强联通分量缩点后的出度为0。即缩点后该点到不了其他点,满足sink的定义。也就是说,该题就是求缩点后哪些点的出度为0,即为答案。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std;
#define CLR(arr,val) memset(arr,val,sizeof(arr))
const int N = 5010;
int low[N],dfn[N],numnode,numedge,head[N],numpath;
int timeorder,ss[N],numss,vis[N],numQ[N],numcnt;
int outdegree[N];
vector<int> vv[N];
struct edge{
int x,y,next;
}ee[N * N];
void add_edge(int lp,int rp){
ee[numedge].x = lp;
ee[numedge].y = rp;
ee[numedge].next = head[lp];
head[lp] = numedge++;
}
int min(int a,int b){
return a < b ? a : b;
}
void targin(int x){
vis[x] = 1;
timeorder++;
numss++;
dfn[x] = low[x] = timeorder;
ss[numss] = x;
for(int i = head[x]; i != -1; i = ee[i].next){
int rp = ee[i].y;
if(!vis[rp]){
targin(rp);
low[x] = min(low[x],low[rp]);
}
else if(vis[rp] == 1){
low[x] = min(low[x],dfn[rp]);
}
}
if(low[x] == dfn[x]){
numcnt++;
while(1){
int tt = ss[numss--];
vis[tt] = 2;
numQ[tt] = numcnt;
vv[numcnt].push_back(tt);
if(tt == x)
break;
}
}
}
void init(){
CLR(low,0);
CLR(dfn,0);
CLR(head,-1);
CLR(ss,0);
CLR(vis,0);
CLR(numQ,0);
CLR(outdegree,0);
CLR(vv,0);
timeorder = 0;
numss = 0;
numedge = 0;
numcnt = 0;
}
int main(){
//freopen("1.txt","r",stdin);
while(scanf("%d",&numnode) && numnode){
scanf("%d",&numpath);
init();
int lp,rp;
for(int i = 0; i < numpath; ++i){
scanf("%d%d",&lp,&rp);
add_edge(lp,rp);
}
for(int i = 1; i <= numnode; ++i){
if(!dfn[i])
targin(i);
}
// printf("numcnt = %d\n",numcnt);
for(int i = 0 ;i < numedge; ++i){
int leftp = numQ[ee[i].x];
int rightp = numQ[ee[i].y];
if(leftp != rightp){
outdegree[leftp]++;
}
}
int ans[N], K = 0;
for(int i = 1; i <= numcnt; ++i){
if(!outdegree[i]){
for(int j = 0;j < vv[i].size(); ++j){
ans[K++] = vv[i][j];
}
}
}
sort(ans,ans+K);
for(int i = 0; i < K-1; ++i)
printf("%d ",ans[i]);
printf("%d\n",ans[K-1]);
}
return 0;
}