Reachability from the Capital(Codeforces Round #490 (Div. 3)+tarjan有向图缩点)

题目链接:http://codeforces.com/contest/999/problem/E

题目:

题意:给你n个城市,m条单向边,问你需要加多少条边才能使得从首都s出发能到达任意一个城市。

思路:tarjan缩点,结果就是缩点新建的图中入度为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 = 5e3 + 7;
 33 const double pi = acos(-1);
 34 const int inf = 0x3f3f3f3f;
 35 const ll INF = 0x3f3f3f3f3f3f3f;
 36 
 37 int n, m, tot, s, cnt, top, u, v, num;
 38 int head[maxn], vis[maxn], in[maxn];
 39 int tot1, head1[maxn], in1[maxn];
 40 int dfn[maxn], low[maxn], c[maxn], stc[maxn];
 41 
 42 struct edge {
 43     int v, next;
 44 }ed[maxn], ed1[maxn];
 45 
 46 void addedge(int u, int v) {
 47     ed[tot].v = v;
 48     ed[tot].next = head[u];
 49     head[u] = tot++;
 50 }
 51 
 52 void addedge1(int u, int v) {
 53     ed1[tot1].v = v;
 54     ed1[tot1].next = head1[u];
 55     head1[u] = tot1++;
 56 }
 57 
 58 void tarjan(int x) {
 59     dfn[x] = low[x] = ++num;
 60     vis[x] = 1, stc[++top] = x;
 61     for(int i = head[x]; ~i; i = ed[i].next) {
 62         int y = ed[i].v;
 63         if(!dfn[y]) {
 64             tarjan(y);
 65             low[x] = min(low[x], low[y]);
 66         } else if(vis[y]) {
 67             low[x] = min(low[x], low[y]);
 68         }
 69     }
 70     if(dfn[x] == low[x]) {
 71         int y; cnt++;
 72         do {
 73             y = stc[top--]; vis[y] = 0;
 74             c[y] = cnt;
 75         } while(x != y);
 76     }
 77 }
 78 
 79 int main() {
 80     //FIN;
 81     scanf("%d%d%d", &n, &m, &s);
 82     memset(head, -1, sizeof(head));
 83     memset(head1, -1, sizeof(head1));
 84     for(int i = 1; i <= m; i++) {
 85         scanf("%d%d", &u, &v);
 86         addedge(u, v);
 87         in[v]++;
 88     }
 89     for(int i = 1; i <= n; i++) {
 90         if(in[i] == 0 && !dfn[i]) {
 91             tarjan(i);
 92         }
 93     }
 94     for(int i = 1; i <= n; i++) {
 95         if(!dfn[i]) {
 96             tarjan(i);
 97         }
 98     }
 99     int sum = 0;
100     for(int i = 1; i <= n; i++) {
101         for(int j = head[i]; ~j; j = ed[j].next) {
102             int y = ed[j].v;
103             if(c[i] == c[y]) continue;
104             addedge1(c[i], c[y]);
105             in1[c[y]]++;
106         } 
107     }
108     s = c[s];
109     for(int i = 1; i <= cnt; i++) {
110         if(i != s && in1[i] == 0) {
111             sum++;
112         }
113     }
114     printf("%d\n", sum);
115     return 0;
116 }

 

posted @ 2018-07-31 21:28  Dillonh  阅读(353)  评论(0编辑  收藏  举报