n个学校构成一个有向图,通过m条边连接,一:问至少向图中多少个学校投放软件,可以使得所有学校直接或者间接的通过边(假设存在边(u,v),则向u投放v可以得到,而向v投放u不能通过v直接得到)得到软件(假设每次投放的软件无穷多)。二:问至少添加多少条边可以使得只用向一个学校投放软件别的学校都能得到软件
输入
第一行给出数字N,N<=100
接下来N行给出每个点的连通情况,每行给出一些数字代表第i个学校与哪些学校相连接,每行输入以0代表结束
输出
如题
Sample Input
5
2 4 3 0
4 5 0
0
0
1 0
Sample Output
1
2
其实就是强连通缩点,
问一是统计缩点后有多少分量入度为0,
问二是指至少添加多少边使得图强连通。
然后统计入度为0的点的个数in和出度为0的点的个数ou,
则问一输出in,问二如果整个图强连通则输出0,否则输出max{in,ou}。
为什么是max{in,ou}?
因为要使得图强连通,则必定每个点的出度以及入度都不为0
#include#include using namespace std; int son[10100],n,m,ans1,group,low[10100],dfn[10100],st[10100],tot,now[10100],used[11000],popp[11000],topp[11000],a[11000],b[11000],ans2; void add(int x,int y) { tot++; now[tot]=son[x]; son[x]=tot; } int top,sum,cnt,totle; void dfs(int deep) { st[++top]=deep; dfn[deep]=++cnt; low[deep]=dfn[deep]; int nnow=top; for(int i=son[deep];i;i=now[i]) if(!used[b[i]]) { if(!dfn[b[i]]) dfs(b[i]); low[deep]=min(low[b[i]],low[deep]); } if(dfn[deep]==low[deep]) { totle++; for(int i=nnow;i<=top;i++) used[st[i]]=totle; top=nnow-1; } } int main() { int v,k=0; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&v); while(v) { add(i,v); a[++k]=i; b[k]=v; scanf("%d",&v); } } for(int i=1;i<=n;i++) if(!used[i])dfs(i); for(int i=1;i<=k;i++) if(used[a[i]]!=used[b[i]]) ++popp[used[a[i]]], topp[used[b[i]]]++; for(int i=1;i<=totle;i++) { if(topp[i]==0) ans1++; if(popp[i]==0) ans2++; } ans2=max(ans1,ans2); if(totle==1) ans2=0; printf("%d\n%d",ans1,ans2); }
#include#include using namespace std; int s[10010],st[110],hea[110],en[110],in[110],dfn[110],low[110],cd[110],rd[110],num,cnt,top,n,m; void tarjan(int x) { low[x]=dfn[x]=++num; st[++top]=x; for(int i=hea[x];i