题意:在单项的网络传输中,把软件发给所有的人。问最少要多少个软件才能所有人都得到软件。问增加多少条边,可以使得给任意一个人一个软件,就可以传播到所有的人。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> using namespace std; const int N = 109; const int M = 10009; const int INF = 0x3f3f3f3f; int n; struct node{ int nex,to; } L[M]; int F[N],cnt; void add(int f,int t) { L[cnt].nex = F[f]; L[cnt].to = t; F[f] = cnt++; } void init() { cnt = 1;memset(F,0,sizeof(F)); for(int i=1,t; i<=n; i++) while(scanf("%d",&t)&&t) add(i,t); } int dfn[N],low[N],ind,col[N],color; bool post[N]; stack<int> S; void tarjan(int k){ dfn[k] = low[k] =ind++; post[k] = true; S.push(k); for(int i=F[k];i;i=L[i].nex){ int to = L[i].to; if(!dfn[to]){ tarjan(to); low[k] = min(low[k],low[to]); }else if(post[to]&&low[k]>dfn[to]){ low[k] = dfn[to]; } } if(dfn[k]==low[k]){ color++;int i; for(i=S.top(),S.pop();i!=k;i=S.top(),S.pop()) { col[i] = color; post[i] = false; } col[i]=color,post[i] = false; } } int tin[N],tou[N]; void solve() { memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); ind = 1;color = 0; for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); if(color==1) { printf("%d\n%d\n",1,0); return ; } memset(tin,0,sizeof(tin)); memset(tou,0,sizeof(tou)); for(int i=1;i<=n;i++) { for(int j=F[i];j;j=L[j].nex) if(col[L[j].to]!=col[i]) { tin[col[L[j].to]]++; tou[col[i]]++; } } int in=0,ou=0; for(int i=1;i<=color;i++) { if(tin[i]==0) in++; if(tou[i]==0) ou++; } printf("%d\n%d\n",in,max(in,ou)); } int main() { freopen("in.txt","r",stdin); while(~scanf("%d",&n)){ init(); solve(); } return 0; }