校园网络
时间限制:3000 ms | 内存限制:65535 KB
难度:5
- 描述
-
南阳理工学院共有M个系,分别编号1~M,其中各个系之间达成有一定的协议,如果某系有新软件可用时,该系将允许一些其它的系复制并使用该软件。但该允许关系是单向的,即:A系允许B系使用A的软件时,B未必一定允许A使用B的软件。
现在,请你写一个程序,根据各个系之间达成的协议情况,计算出最少需要添加多少个两系之间的这种允许关系,才能使任何一个系有软件使用的时候,其它所有系也都有软件可用。
- 输入
- 第一行输入一个整数T,表示测试数据的组数(T<10)
每组测试数据的第一行是一个整数M,表示共有M个系(2<=M<=100)。
随后的M行,每行都有一些整数,其中的第i行表示系i允许这几个系复制并使用系i的软件。每行结尾都是一个0,表示本行输入结束。如果某个系不允许其它任何系使用该系软件,则本行只有一个0.
- 输出
- 对于每组测试数据,输出最少需要添加的这种允许关系的个数。
- 样例输入
-
1 5 2 4 3 0 4 5 0 0 0 1 0
- 样例输出
-
2
- 来源
- POJ改编
-
上传者
<pre name="code" class="cpp">#include<stdio.h> #include<string.h> #include<queue> #include<stack> #include<vector> #include<algorithm> using namespace std; #define MAXN 50010 int in[MAXN],out[MAXN],sumin,sumout; vector<int>G[MAXN]; vector<int>scc[MAXN]; struct node { int u,v; int next; }edge[MAXN]; int head[MAXN],cnt,scc_cnt,dfs_clock; int sccno[MAXN],low[MAXN],dfn[MAXN]; bool Instack[MAXN]; int n; stack<int>s; void init() { memset(head,-1,sizeof(head)); cnt=0; } void add(int u,int v) { node E={u,v,head[u]}; edge[cnt]=E; head[u]=cnt++; } void getmap() { for(int i=1,a;i<=n;i++) { while(scanf("%d",&a),a) add(i,a); } } void suodian() { for(int i=1;i<=scc_cnt;i++) G[i].clear(),in[i]=0,out[i]=0; for(int i=0;i<n;i++) { int u=sccno[edge[i].u]; int v=sccno[edge[i].v]; if(u!=v) out[u]++,in[v]++; } } void tarjan(int u,int fa) { int v; low[u]=dfn[u]=++dfs_clock; s.push(u); Instack[u]=true; for(int i=head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(!dfn[v]) { tarjan(v,u); low[u]=min(low[u],low[v]); } else if(Instack[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { scc_cnt++; scc[scc_cnt].clear(); for(;;) { v=s.top(); s.pop(); Instack[v]=false; sccno[v]=scc_cnt; scc[scc_cnt].push_back(v); if(u==v) break; } } } void solve() { sumin=sumout=0; if(scc_cnt==1) printf("0 "); else { for(int i=1;i<=scc_cnt;i++) { if(in[i]==0) sumin++; if(out[i]==0) sumout++; } int sum=max(sumin,sumout); printf("%d ",sum); } } void find(int l,int r) { memset(Instack,false,sizeof(Instack)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(sccno,0,sizeof(sccno)); dfs_clock=scc_cnt=0; for(int i=l;i<=r;i++) if(!dfn[i]) tarjan(i,-1); } int main() { int t; scanf("%d",&t); while(t--) { init(); scanf("%d",&n); getmap(); find(1,n); suodian(); solve(); } }