HDU 2767 Proving Equivalences

嘟嘟嘟

题目大意:给一个有向图,问至少几条边,使其成为强连通图。

首先强联通缩点,然后分别统计入度为0的点数num1和出度为0的点数num2,答案就是max(num1, num2)。

为什么呢?不难想,入度为0说明没有点能到达他,所以必须连一条通向他的边;出度为0说明他不能通向任何点,所以也得连一条出边。于是这些点可以互相连,多出去的就再连别的点。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 using namespace std;
 12 #define enter puts("") 
 13 #define space putchar(' ')
 14 #define Mem(a, x) memset(a, x, sizeof(a))
 15 #define rg register
 16 typedef long long ll;
 17 typedef double db;
 18 const int INF = 0x3f3f3f3f;
 19 const db eps = 1e-8;
 20 const int maxn = 2e4 + 5;
 21 inline ll read()
 22 {
 23     ll ans = 0;
 24     char ch = getchar(), last = ' ';
 25     while(!isdigit(ch)) {last = ch; ch = getchar();}
 26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
 27     if(last == '-') ans = -ans;
 28     return ans;
 29 }
 30 inline void write(ll x)
 31 {
 32     if(x < 0) x = -x, putchar('-');
 33     if(x >= 10) write(x / 10);
 34     putchar(x % 10 + '0');
 35 }
 36 
 37 int n, m;
 38 vector<int> v[maxn];
 39 
 40 stack<int> st;
 41 bool in[maxn];
 42 int dfn[maxn], low[maxn], cnt = 0;
 43 int col[maxn], ccol = 0;
 44 void tarjan(int now)
 45 {
 46     dfn[now] = low[now] = ++cnt;
 47     st.push(now); in[now] = 1;
 48     for(int i = 0; i <(int)v[now].size(); ++i)
 49     {
 50         if(!dfn[v[now][i]])
 51         {
 52             tarjan(v[now][i]);
 53             low[now] = min(low[now], low[v[now][i]]);
 54         }
 55         else if(in[v[now][i]]) low[now] = min(low[now], dfn[v[now][i]]);
 56     }
 57     if(dfn[now] == low[now])
 58     {
 59         int x; ++ccol;
 60         do
 61         {
 62             x = st.top(); st.pop();
 63             in[x] = 0;
 64             col[x] = ccol;
 65         }while(x != now);
 66     }
 67 }
 68 
 69 int ind[maxn], oud[maxn], Mi = 0, Mo = 0;
 70 void newGraph(int now)
 71 {
 72     int u = col[now];
 73     for(int i = 0; i < (int)v[now].size(); ++i)
 74     {
 75         int e = col[v[now][i]];
 76         if(u == e) continue;
 77         oud[u]++; ind[e]++;
 78     }
 79 }
 80 
 81 void init()
 82 {
 83     for(int i = 0; i < maxn; ++i) v[i].clear();
 84     while(!st.empty()) st.pop();
 85     Mem(dfn, 0); Mem(low, 0); Mem(in, 0);
 86     Mem(col, 0);
 87     cnt = ccol = 0;
 88     Mem(ind, 0); Mem(oud, 0); Mi = Mo = 0;
 89 }
 90 
 91 int main()
 92 {
 93     int T = read();
 94     while(T--)
 95     {
 96         init();
 97         n = read(); m = read();
 98         for(int i = 1; i <= m; ++i)
 99         {
100             int x = read(), y = read();
101             v[x].push_back(y);
102         }
103         for(int i = 1; i <= n; ++i) if(!dfn[i]) tarjan(i);
104         for(int i = 1; i <= n; ++i) newGraph(i); 
105         if(ccol == 1) {write(0), enter; continue;}
106         for(int i = 1; i <= ccol; ++i)
107         {
108             if(!ind[i]) Mi++;
109             if(!oud[i]) Mo++;
110         }
111         write(max(Mi, Mo)); enter;
112     }
113     return 0;
114 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9669990.html