POJ1236--Network of Schools(强连通+缩点)
第一问:至少需要多少份软件,才能使得所有学校都能拥有软件;第二问:如果只用一份软件,那么需要添加多少条变,使得所有学校都能拥有软件。
第一问中,如果一个学校有用一份软件,那么它的强连通分量中的其他学校,肯定也能够拥有软件,所以只要求出出度为0的强连通分量的个数即可。
第二问中,就是求需要添加多少条变,使得整个图都成为一个强连通,即任意两个学校都可到达,所以我们只要求出出度为0的个数a,和入度为0的个数b,取两者的最大值即可。
#include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <stack> #include <vector> #define M 105 using namespace std; int dfn[M],low[M],scc_cnt,index; int sccno[M]; stack<int> s; vector<int> G[M]; void Tarjan(int u) { dfn[u]=low[u]=++index; s.push(u); for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(!dfn[v]) { Tarjan(v); low[u]=min(low[u],low[v]); } else if(!sccno[v]) { low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]) { scc_cnt++; for(;;) { int x=s.top(); s.pop(); sccno[x]=scc_cnt; if(x==u) break; } } } void find_scc(int n) { index=scc_cnt=0; memset(sccno,0,sizeof(sccno)); memset(dfn,0,sizeof(dfn)); for(int i=0;i<n;i++) if(!dfn[i]) Tarjan(i); } int main() { int n; int in0[M],out0[M]; while(scanf("%d",&n)!=EOF) { for(int i=0;i<n;i++) G[i].clear(); for(int i=0;i<n;i++) { int v; while(scanf("%d",&v)) { if(v==0) break; v--; G[i].push_back(v); } } find_scc(n); for(int i=1;i<=scc_cnt;i++) in0[i]=out0[i]=1; for(int u=0;u<n;u++) { for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(sccno[u]!=sccno[v]) in0[sccno[v]]=out0[sccno[u]]=0; } } int a=0,b=0; for(int i=1;i<=scc_cnt;i++) { if(in0[i]) a++; if(out0[i]) b++; } int ans=max(a,b); if(scc_cnt==1) ans=0; printf("%d\n%d\n",a,ans); } return 0; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。