[HDU] 3836 Equivalent Sets
题目大意为给定一张有向图,求加多少条边之后整个图是一张强连通分量。
思路大致是:先将图中的强连通分量缩点,使得图变成一张无环图,这个时候图上剩余k1个出度为0的点和k2个入度为0的点,将出度为0的点连一条有向边到入度为0的点,此时形成一个环,这个环是一个强连通分量,可以再缩成一个点,当图中只剩一个点的时候,就完成了任务。显而易见的是最大只要连接max{k1,k2}条边,就能将所有的点缩成一个点。
#include<stdio.h> typedef struct edge { int x; edge *n; }; bool f[30000]; edge *e[30000],*g[30000]; int q[30000],mark[30000],u[30000],v[30000],num,n,m; void addedge(int x,int y) { edge *p; p=new edge; p->x=y; p->n=e[x]; e[x]=p; p=new edge; p->x=x; p->n=g[y]; g[y]=p; } void search(int t) { edge *p; p=e[t]; f[t]=true; while (p!=NULL) { if (!f[p->x]) search(p->x); p=p->n; } q[++num]=t; } void build(int t,int m) { edge *p; p=g[t]; f[t]=false; mark[t]=m; while (p!=NULL) { if (f[p->x]) build(p->x,m); p=p->n; } } int main() { int i,x,y; while (scanf("%d%d",&n,&m)!=EOF) { for (i=1; i<=n; i++) e[i]=g[i]=NULL; for (i=0; i<m; i++) { scanf("%d%d",&x,&y); addedge(x,y); } for (i=1; i<=n; i++) f[i]=false; num=0; for (i=1; i<=n; i++) if (!f[i]) search(i); num=0; for (i=n; i>=1; i--) if (f[q[i]]) { num++; build(q[i],num); } for (i=1; i<=num; i++) u[i]=v[i]=0; for (i=1; i<=n; i++) { edge *p; p=e[i]; while (p!=NULL) { if (mark[i]!=mark[p->x]) { u[mark[i]]++; v[mark[p->x]]++; } p=p->n; } } int k1=0,k2=0; for (i=1; i<=num; i++) { if (u[i]==0) k1++; if (v[i]==0) k2++; } if (num==1) printf("0\n"); else if (k1>k2) printf("%d\n",k1); else printf("%d\n",k2); } return 0; }