USACO 5.3 Network of Schools (强连通分量,缩点)

2015-03-31 23:31:55

思路:给出一个有向图,让你求最少给多少个点(学校)发软件,能使得软件传到全部点(学校)。

     另外还有第二问:添加最少的边使得给任意一点(学校)发软件,能传到全部点(学校)。

  一开始是想直接并查集乱搞... 后来明白题意后... 首先强连通分量里面的点是互相可达的,所以先tarjan一遍再缩点。

  接着考虑第一问,显然是找出缩点后所有入度为0的点,其数量便是第一个答案。

  然后考虑第二问,这个问题以前hdu2767一样,添加最少边使得整个图强连通,那么答案就是缩点后:max(入度为0的点数,出度为0的点数)

  1 /*
  2 ID:naturec1
  3 PROG: schlnet
  4 LANG: C++
  5 */
  6 #include <cstdio>
  7 #include <cstring>
  8 #include <cstdlib>
  9 #include <cmath>
 10 #include <vector>
 11 #include <map>
 12 #include <set>
 13 #include <stack>
 14 #include <queue>
 15 #include <string>
 16 #include <iostream>
 17 #include <algorithm>
 18 using namespace std;
 19 
 20 #define MEM(a,b) memset(a,b,sizeof(a))
 21 #define REP(i,n) for(int i=0;i<(n);++i)
 22 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
 23 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
 24 #define MP(a,b) make_pair(a,b)
 25 
 26 typedef long long ll;
 27 typedef pair<int,int> pii;
 28 const int INF = (1 << 30) - 1;
 29 const int MAXN = 110;
 30 
 31 int N,tot,scnt;
 32 int first[MAXN],ecnt;
 33 int dfn[MAXN],low[MAXN],sc[MAXN];
 34 int din[MAXN],dout[MAXN];
 35 stack<int> stk;
 36 
 37 struct edge{
 38     int v,next;
 39 }e[MAXN * MAXN];
 40 
 41 void Init(){
 42     MEM(first,-1);
 43     ecnt = 0;
 44     tot = 0;
 45     scnt = 0;
 46 }
 47 
 48 void Add_edge(int u,int v){
 49     e[++ecnt].next = first[u];
 50     e[ecnt].v = v;
 51     first[u] = ecnt;
 52 }
 53 
 54 void Dfs(int p){
 55     dfn[p] = low[p] = ++tot;
 56     stk.push(p);
 57     for(int i = first[p]; ~i; i = e[i].next){
 58         int v = e[i].v;
 59         if(!dfn[v]){
 60             Dfs(v);
 61             low[p] = min(low[p],low[v]);
 62         }
 63         else if(!sc[v]){
 64             low[p] = min(low[p],dfn[v]);
 65         }
 66     }
 67     if(dfn[p] == low[p]){
 68         scnt++;
 69         for(;;){
 70             int x = stk.top(); stk.pop();
 71             sc[x] = scnt;
 72             if(x == p) break;
 73         }
 74     }
 75 }
 76 
 77 void Tarjan(){
 78     MEM(low,0);
 79     MEM(dfn,0);
 80     MEM(sc,0);
 81     while(!stk.empty()) stk.pop();
 82     FOR(i,1,N){
 83         if(!dfn[i]) Dfs(i);
 84     }
 85 }
 86 
 87 int main(){
 88     freopen("schlnet.in","r",stdin);
 89     freopen("schlnet.out","w",stdout);
 90     int a;
 91     Init();
 92     scanf("%d",&N);
 93     FOR(i,1,N){
 94         while(scanf("%d",&a) != EOF && a){
 95             Add_edge(i,a);
 96         }
 97     }
 98     Tarjan();
 99     FOR(i,1,N){
100         for(int j = first[i]; ~j; j = e[j].next){
101             int v = e[j].v;
102             if(sc[i] != sc[v]){
103                 dout[sc[i]]++;
104                 din[sc[v]]++;
105             }
106         }
107     }
108     int cnt1 = 0,cnt2 = 0;
109     FOR(i,1,scnt) if(din[i] == 0) cnt1++;
110     FOR(i,1,scnt) if(dout[i] == 0) cnt2++;
111     int ans1 = cnt1 == 0 ? 1 : cnt1;
112     int ans2 = scnt == 1 ? 0 : max(cnt1,cnt2);
113     printf("%d\n%d\n",ans1,ans2);
114     return 0;
115 }

 

posted @ 2015-03-31 23:41  Naturain  阅读(114)  评论(0编辑  收藏  举报