题意: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; }