http://poj.org/problem?id=1236
Description
Input
Output
Sample Input
5 2 4 3 0 4 5 0 0 0 1 0
Sample Output
1 2题目大意:给出N台电脑,电脑间单向连通传送文件
#include <stdio.h> #include <string.h> #include <iostream> using namespace std; #define M 10005 #define N 105 struct edge//链式前向星存储图 { int v,next; }edge[M]; int head[N],stack[N],ins[N],dfn[N],out[N],in[N]; int low[N],belong[N],index,cnt_edge,n,m,cnt_tar,top; int ee[M][2]; void add_edge(int u,int v)//新增一条边的操作 { edge[cnt_edge].v=v; edge[cnt_edge].next=head[u]; head[u]=cnt_edge++; } void tarjan(int u)//求强连通量的Tarjan算法(模板) { int j,i,v; dfn[u]=low[u]=++index;//为节点u设定次序编号和low初值 stack[++top]=u;//将节点u压入栈中 ins[u]=1; for(i=head[u];i!=-1;i=edge[i].next)//枚举每一条边 { v=edge[i].v; if(!dfn[v])//如果节点v未被访问过 { tarjan(v);//继续向下找 low[u]=min(low[u],low[v]); } else if(ins[v])//如果节点还在栈内 low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u])//如果节点u是强连通分量的根 { cnt_tar++;//计数加一 do { j=stack[top--];//将v退栈 ins[j]=0;//不再栈内了 belong[j]=cnt_tar;//该强连通分量的最后一个出栈的点作为一个缩点出现在新的待建的图中作为该强连通分量的代表 }while(j!=u); } } void solve() { int i; top=0,index=0,cnt_tar=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); for(i=1;i<=n;i++)//求强连通分量时遍历每一个点 { if(!dfn[i]) tarjan(i); } } int main() { int i,u,v; while(~scanf("%d",&n)) { cnt_edge=0,m=1; memset(head,-1,sizeof(head));//head数组置-1 memset(in,0,sizeof(in));//统计入度为零的强连通分量的个数 memset(out,0,sizeof(out));//统计初度为零的点的强连通分量的个数 for(i=1;i<=n;i++) { while(scanf("%d",&v)) { if(v==0) break; ee[m][0]=i,ee[m++][1]=v;//前者为一条路的起点,后者为终点 add_edge(i,v); } } solve();//求强连通分量 for(i=1;i<=m;i++) { int xx=belong[ee[i][0]],yy=belong[ee[i][1]]; if(xx!=yy) { in[yy]++;//二者不相等则路的终点多对应的点的入度肯定不为零 out[xx]++;//同上,出度不为零 } } int innum=0,outnum=0; for(i=1;i<=cnt_tar;i++) { if(in[i]==0)//统计出度 innum++; if(out[i]==0)//统计入度 outnum++; } if(cnt_tar==1) printf("1\n0\n"); else printf("%d\n%d\n",innum,max(innum,outnum)); } return 0; }