Some schools are connected to a computer network. There is a software support agreement between schools. Each school has a list of schools it should support (school AAA supports school BBB, does not mean that the school BBB must support school AAA ). When a school receives a new software, whether it gets it directly or through the network, the school should establish a transfer of the software to the school it should support through the network. Therefore, to use a new software for all schools connected to the Internet, you only need to provide it to some schools.
Task
- Compile a program to calculate the minimum number of schools that need to provide a new software directly according to the inter-school support agreement (the support list for each school, so that the software can be transmitted to all schools through the network;
- If new support relationships can be added to the original support agreement. A new protocol can always be formed, so that a new software can be provided to any school, and all other schools can obtain the software through the network. At least a few new support relationships need to be added for programming computing.
First of all, it is clear that a strongly connected component must meet the above requirements.
So we first perform the point reduction operation of Tarjan.
Then the edge is connected. For a point with zero inbound, we must tell one of them.
Then the first question is solved (recording the input level during the EDGE connection process)
The second question is, because it is any school, we need to add an inbound edge from every school to another school, that is, from every place with zero degree of exit.
Add an outbound edge to a place with zero inbound
One outbound edge and the inbound edge can correspond one by one, so you only need to go to the larger one of the two values.
Note that if there is only one vertex, juin does not need to be connected to edges, and special judgment should be added to the output.
The following code is provided:
#include<iostream>#include<algorithm>#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>using namespace std;inline int rd(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘; return x*f;}inline void write(int x){ if(x<0) putchar(‘-‘),x=-x; if(x>9) write(x/10); putchar(x%10+‘0‘); return ;}int n;int head[1000006],nxt[1000006],to[1000006];int total=0;void add(int x,int y){ total++; to[total]=y; nxt[total]=head[x]; head[x]=total; return ;}int tot=0;int dfn[1000006];int low[1000006];int sta[1000006];int book[1000006];int set=0;int color[1000006];int cnt=0;void tarjan(int x){ low[x]=dfn[x]=++tot; sta[++set]=x; book[x]=1; for(int e=head[x];e;e=nxt[e]){ if(!dfn[to[e]]){ tarjan(to[e]); low[x]=min(low[x],low[to[e]]); } else if(book[to[e]]) low[x]=min(low[x],dfn[to[e]]); } if(dfn[x]==low[x]){ book[x]=0; cnt++; color[x]=cnt; while(sta[set]!=x){ book[sta[set]]=0; color[sta[set]]=cnt; set--; } set--; } return ;}int du[1000006];int du2[1000006];int main(){ n=rd(); for(int i=1;i<=n;i++){ int x; while(x=rd()) add(i,x); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++){ for(int e=head[i];e;e=nxt[e]){ if(color[i]!=color[to[e]]){ du[color[to[e]]]++; du2[color[i]]++; } } } int ans=0; int num=0; for(int i=1;i<=cnt;i++){ if(du[i]==0) ans++; if(du2[i]==0) num++; } write(ans);puts(""); write(cnt==1?0:max(ans,num)); return 0;}
IOI 1996 network protocol