Network of Schools(POJ1326+有向图进行缩点)

题目链接:http://poj.org/problem?id=1236

题目:

题意:对于n个学校,对于一个系统传给某个学校,那么他会传给他得支援学校。从第二开始,每行给你多个数字,表示第i个学校可以支援这些学校,以0结尾。问你一个新软件至少要给多少个学校,如果任意传给某个学校都能传给其他学校需要建多少条支援关系。

思路:tarjan进行缩点,重新建图,对新建得有向无环图统计一下出度和入度,第一问答案就是入度为0的数量,第二问则是max(入度为0的个数,出度为0的个数)。

代码实现如下:

  1 #include <set>
  2 #include <map>
  3 #include <queue>
  4 #include <stack>
  5 #include <cmath>
  6 #include <bitset>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15 
 16 typedef long long ll;
 17 typedef pair<ll, ll> pll;
 18 typedef pair<ll, int> pli;
 19 typedef pair<int, ll> pil;;
 20 typedef pair<int, int> pii;
 21 typedef unsigned long long ull;
 22 
 23 #define lson i<<1
 24 #define rson i<<1|1
 25 #define bug printf("*********\n");
 26 #define FIN freopen("D://code//in.txt", "r", stdin);
 27 #define debug(x) cout<<"["<<x<<"]" <<endl;
 28 #define IO ios::sync_with_stdio(false),cin.tie(0);
 29 
 30 const double eps = 1e-8;
 31 const int mod = 10007;
 32 const int maxn = 100 + 7;
 33 const double pi = acos(-1);
 34 const int inf = 0x3f3f3f3f;
 35 const ll INF = 0x3f3f3f3f3f3f3f;
 36 
 37 int n, tot, x, cnt, num, top;
 38 int head[maxn], c[maxn];
 39 int in[maxn], out[maxn], vis[maxn];
 40 int dfn[maxn], low[maxn], stc[maxn];
 41 
 42 void init() {
 43     tot = cnt= num = top = 0;
 44     memset(c, 0, sizeof(c));
 45     memset(in, 0, sizeof(in));
 46     memset(out, 0, sizeof(out));
 47     memset(vis, 0, sizeof(vis));
 48     memset(stc, 0, sizeof(stc));
 49     memset(dfn, 0, sizeof(dfn));
 50     memset(low, 0, sizeof(low));
 51     memset(head, -1, sizeof(head));
 52 }
 53 
 54 struct edge {
 55     int v, next;
 56 }ed[maxn*maxn];
 57 
 58 void addedge(int u, int v) {
 59     ed[tot].v = v;
 60     ed[tot].next = head[u];
 61     head[u] = tot++;
 62 }
 63 
 64 void tarjan(int x) {
 65     dfn[x] = low[x] = ++num;
 66     stc[++top] = x, vis[x] = 1;
 67     for(int i = head[x]; ~i; i = ed[i].next) {
 68         int y = ed[i].v;
 69         if(!dfn[y]) {
 70             tarjan(y);
 71             low[x] = min(low[x], low[y]);
 72         } else if(vis[y]) {
 73             low[x] = min(low[x], low[y]);
 74         }
 75     }
 76     if(dfn[x] == low[x]) {
 77         cnt++; int y;
 78         do {
 79             y = stc[top--]; vis[y] = 0;
 80             c[y] = cnt;
 81         }while(x != y);
 82     }
 83 }
 84 
 85 int main() {
 86     //FIN;
 87     scanf("%d", &n);
 88     init();
 89     for(int i = 1; i <= n; i++) {
 90         while(1) {
 91             scanf("%d", &x);
 92             if(x == 0) break;
 93             addedge(i, x);
 94         }
 95     }
 96     for(int i = 1; i <= n; i++) {
 97         if(!dfn[i]) {
 98             tarjan(i);
 99         }
100     }
101     for(int i = 1; i <= n; i++) {
102         for(int j = head[i]; ~j; j = ed[j].next) {
103             int y = ed[j].v;
104             if(c[i] == c[y]) continue;
105             out[c[i]]++;
106             in[c[y]]++;
107         }
108     }
109     if(cnt == 1) {
110         printf("1\n0\n");
111         return 0;
112     }
113     int ans1 = 0, ans2 = 0;
114     for(int i = 1; i <= cnt; i++) {
115         if(in[i] == 0) ans1++;
116         if(out[i] == 0) ans2++;
117     }
118     printf("%d\n%d\n", ans1, max(ans1, ans2));
119     return 0;
120 }

 

posted @ 2018-07-31 20:23  Dillonh  阅读(167)  评论(0编辑  收藏  举报