题目大意是给定一个有向图,求最少需添加多少条有向边使得原图强连通。可以先求强连通分量,统计缩点后的图中入度为0的点和出度为0的点,答案就是两者中的较大者,需要注意的是当原图是强连通时,直接输出0。因为没有初始化WA了一次。
#include <stdio.h> #include <string.h> #define CLR(a) (memset(a,0,sizeof(a))) #define N 100 char g[N][N],vis[N]; int n; int ord[N],id[N],cnt,din[N],dout[N]; void dfs(int u) { int v; vis[u]=1; for(v=0;v<n;v++) { if(g[u][v]&&!vis[v]) dfs(v); } ord[cnt++]=u; } void rdfs(int u) { int v; vis[u]=1,id[u]=cnt; for(v=0;v<n;v++) { if(g[v][u]&&!vis[v]) rdfs(v); } } void kosaraju() { int i,j,t,a,b; CLR(vis); for(i=0,cnt=0;i<n;i++) { if(!vis[i]) dfs(i); } CLR(vis); for(t=n-1,cnt=0;t>=0;t--) { i=ord[t]; if(!vis[i]) { rdfs(i),cnt++; } } CLR(din),CLR(dout); for(i=0;i<n;i++) { for(j=i+1;j<n;j++) { if((id[i]^id[j]) && (g[i][j] || g[j][i])) { dout[id[i]]+=g[i][j],din[id[j]]+=g[i][j]; dout[id[j]]+=g[j][i],din[id[i]]+=g[j][i]; } } } for(i=0,a=0,b=0;i<cnt;i++) a+=dout[i]==0?1:0,b+=din[i]==0?1:0; if(cnt==1) printf("0\n"); else printf("%d\n",a>b?a:b); } int main() { int i,j; while(~scanf("%d",&n)) { CLR(g); for(i=0;i<n;i++) { while(scanf("%d",&j)&&j) g[i][j-1]=1; } kosaraju(); } return 0; }