d.各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输,
问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。
问题2:至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。
s.
首先找强连通分量,然后看强连通分量的入度为0点的总数,出度为0点的总数。
第一问为入度为0的强连通分量的个数。
第二问为入度为0的个数和出度为0的个数中大的。(将这个图的所有子树找出来,然后将一棵子树的叶子结点(出度为0)连到另外一棵子树的根结点上(入度为0),这样将所有的叶子结点和根节点全部消掉之后,就可以得到一整个强连通分量,看最少多少条边,这样就是看叶子结点和根节点哪个多,即出度为0和入度为0哪个多。证明?)
c.Tarjan
/* Tarjan算法 复杂度O(N+M) */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int MAXN=110;//点数 const int MAXM=10100;//边数 struct Edge{ int to,next; }edge[MAXM]; int head[MAXN],tot; int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~scc int Index,top; int scc;//强连通分量的个数 bool Instack[MAXN]; int num[MAXN];//各个强连通分量包含点的个数,数组编号1~scc //num数组不一定需要,结合实际情况 void addedge(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void Tarjan(int u){ int v; Low[u]=DFN[u]=++Index; Stack[top++]=u; Instack[u]=true; for(int i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to; if(!DFN[v]){ Tarjan(v); if(Low[u]>Low[v])Low[u]=Low[v]; } else if(Instack[v]&&Low[u]>DFN[v]) Low[u]=DFN[v]; } if(Low[u]==DFN[u]){ scc++; do{ v=Stack[--top]; Instack[v]=false; Belong[v]=scc; num[scc]++; } while(v!=u); } } void solve(int N){ memset(DFN,0,sizeof(DFN)); memset(Instack,false,sizeof(Instack)); memset(num,0,sizeof(num)); Index=scc=top=0; for(int i=1;i<=N;i++) if(!DFN[i]) Tarjan(i); } void init(){ tot=0; memset(head,-1,sizeof(head)); } int main(){ int N; int v; int indegree[MAXN],outdegree[MAXN];//强连通分量的入度,强连通分量的出度 int in0,out0;//入度为0的强连通分量个数,出度为0的... while(~scanf("%d",&N)){ init(); memset(indegree,0,sizeof(indegree)); memset(outdegree,0,sizeof(outdegree)); in0=out0=0; for(int u=1;u<=N;++u){ while(scanf("%d",&v)){ if(v==0)break; addedge(u,v); } } solve(N); if(scc==1)printf("1\n0\n");//只有一个强连通 分量 else{ //枚举所有的边,统计强连通分量的入度、出度 for(int i=1;i<=N;++i){ for(int j=head[i];j!=-1;j=edge[j].next){ if(Belong[i]!=Belong[edge[j].to]){ ++indegree[Belong[edge[j].to]]; ++outdegree[Belong[i]]; } } } //强连通分量的入度为0的个数,出度为0的个数 for(int i=1;i<=scc;++i){ if(indegree[i]==0)++in0; if(outdegree[i]==0)++out0; } if(in0>out0)printf("%d\n%d\n",in0,in0); else printf("%d\n%d\n",in0,out0); } } return 0; }
时间: 2024-10-10 21:13:21