题意:2553:定义图的bottom集合为:bottom(G)={v∈V|∀w∈V:(v→w)⇒(w→v)}。
对于3180,谁能告诉我这个题是什么意思?看了别人的解答是求点数大于等于2的强连通分量的个数,可是为什么呢?
思路:依题意,所求即求出强连通分量缩点后出度为0的那些强连通分量中得点。用tarjan算法即可。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define clr(s,t) memset(s,t,sizeof(s))
#define N 5005
struct edge{
int y,next;
}e[N*N];
int stack[N],first[N],dfn[N],low[N],instack[N],strong[N];
int n,m,top,id,st,con;
void init(){
top = id = st = con = 0;
clr(first,-1);
clr(dfn,-1);
clr(instack, 0);
}
int cmp(const void* a,const void* b){
return (*(int*)a) - (*(int*)b);
}
void add(int x,int y){
e[top].y = y;
e[top].next = first[x];
first[x] = top++;
}
void tarjan(int x){
int i,y;
dfn[x] = low[x] = ++id;
stack[st++] = x;
instack[x] = 1;
for(i = first[x];i!=-1;i=e[i].next){
y = e[i].y;
if(dfn[y]==-1){
tarjan(y);
low[x] = min(low[x],low[y]);
}else if(instack[y])
low[x] = min(low[x],dfn[y]);
}
if(dfn[x] == low[x]){
con ++;
do{
strong[stack[--st]] = con;
instack[stack[st]] = 0;
}while(stack[st] != x);
}
}
int main(){
while(scanf("%d",&n) && n){
int a,b,i,j;
init();
scanf("%d",&m);
for(i = 0;i<m;i++){
scanf("%d %d",&a,&b);
add(a,b);
}
for(i = 1;i<=n;i++)
if(dfn[i] == -1)
tarjan(i);
clr(dfn, 0);
for(i = 1;i<=n;i++)
for(j = first[i];j!=-1;j=e[j].next)
if(strong[i] != strong[e[j].y])
dfn[strong[i]] = 1;
clr(first,0);
for(top=0,i=1;i<=n;i++)
if(!dfn[strong[i]])
first[top++] = i;
qsort(first,top,sizeof(int),cmp);
for(i = 0;i<top;i++)
printf("%d ",first[i]);
putchar('\n');
}
return 0;
}
3180:
#include <stdio.h>
#include <string.h>
#define N 10005
#define INF 0x3fffffff
#define clr(s,t) memset(s,t,sizeof(s))
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
struct edge{
int y,next;
}e[50005];
int dfn[N],low[N],first[N],stack[N],inst[N];
int n,m,id,top,con,st,res;
void init(){
top = id = con = st = res = 0;
clr(first, -1);
clr(dfn, -1);
clr(inst, 0);
}
void add(int x,int y){
e[top].y = y;
e[top].next = first[x];
first[x] = top++;
}
void tarjan(int x){
int i,y,num=0;
dfn[x] = low[x] = ++id;
stack[st++] = x;
inst[x] = 1;
for(i = first[x];i!=-1;i=e[i].next){
y = e[i].y;
if(dfn[y] == -1){
tarjan(y);
low[x] = min(low[x], low[y]);
}else if(inst[y])
low[x] = min(low[x], dfn[y]);
}
if(dfn[x] == low[x]){
con++;
do{
--st;
inst[stack[st]] = 0;
num++;
}while(x != stack[st]);
if(num >= 2)
res++;
}
}int main(){
while(scanf("%d %d",&n,&m) != EOF){
int i,a,b;
init();
for(i = 0;i<m;i++){
scanf("%d %d",&a,&b);
add(a,b);
}
for(i = 1;i<=n;i++)
if(dfn[i] == -1)
tarjan(i);
printf("%d\n",res);
}
return 0;
}