zoukankan      html  css  js  c++  java
  • UVALive

    Problem   UVALive - 4287 - Proving Equivalences

    Time Limit: 3000 mSec

    Problem Description

    Input

    Output

    Sample Input

    2 4 0 3 2 1 2 1 3

    Sample Output

    4

    2

    题解:题意就是给出一个有向图,问最少添加几条有向边能够使得整张图强连通,Tarjan缩点是比较容易想到的,之后怎么办,要用到一个结论:如果图中有a个入度为零的点,b个出度为零的点,那么max(a, b)就是答案,这个东西不太容易严格证明(在一份ppt上看到说证明难,略。。。),但是形式上想一想还是挺对的。此外mark两个结论,这两个是很容易严格证明的:

      1、DAG中唯一出度为0的点一定可以由任意点出发到达。(证明:由于无环,因此所有点都要终止在出度为0的点)

      2、DAG中所有入度不为0的点一定可以由某个入度为0的点出发到达。(证明:由于无环,入度不为零的点逆着走一定终止在入度为0的点)

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 #define REP(i, n) for (int i = 1; i <= (n); i++)
      6 #define sqr(x) ((x) * (x))
      7 
      8 const int maxn = 20000 + 10;
      9 const int maxm = 30 + 10;
     10 const int maxs = 10000 + 10;
     11 
     12 typedef long long LL;
     13 typedef pair<int, int> pii;
     14 typedef pair<double, double> pdd;
     15 
     16 const LL unit = 1LL;
     17 const int INF = 0x3f3f3f3f;
     18 const LL mod = 1000000007;
     19 const double eps = 1e-14;
     20 const double inf = 1e15;
     21 const double pi = acos(-1.0);
     22 
     23 int n, m;
     24 vector<int> G[maxn];
     25 int dfs_clock, scc_cnt;
     26 int pre[maxn], sccno[maxn];
     27 stack<int> S;
     28 
     29 int dfs(int u)
     30 {
     31     S.push(u);
     32     int lowu = pre[u] = ++dfs_clock;
     33     for (auto v : G[u])
     34     {
     35         if (!pre[v])
     36         {
     37             int lowv = dfs(v);
     38             lowu = min(lowu, lowv);
     39         }
     40         else if (!sccno[v])
     41         {
     42             lowu = min(lowu, pre[v]);
     43         }
     44     }
     45     if (lowu == pre[u])
     46     {
     47         scc_cnt++;
     48         for (;;)
     49         {
     50             int t = S.top();
     51             S.pop();
     52             sccno[t] = scc_cnt;
     53             if (t == u)
     54                 break;
     55         }
     56     }
     57     return lowu;
     58 }
     59 
     60 void find_scc()
     61 {
     62     dfs_clock = scc_cnt = 0;
     63     memset(pre, 0, sizeof(pre));
     64     memset(sccno, 0, sizeof(sccno));
     65     for (int i = 0; i < n; i++)
     66     {
     67         if (!pre[i])
     68         {
     69             dfs(i);
     70         }
     71     }
     72 }
     73 
     74 int out[maxn], in[maxn];
     75 
     76 int main()
     77 {
     78     ios::sync_with_stdio(false);
     79     cin.tie(0);
     80     //freopen("input.txt", "r", stdin);
     81     //freopen("output.txt", "w", stdout);
     82     int T;
     83     cin >> T;
     84     while (T--)
     85     {
     86         memset(out, 0, sizeof(out));
     87         memset(in, 0, sizeof(in));
     88         cin >> n >> m;
     89         for (int i = 0; i < n; i++)
     90         {
     91             G[i].clear();
     92         }
     93         int u, v;
     94         for (int i = 0; i < m; i++)
     95         {
     96             cin >> u >> v;
     97             u--, v--;
     98             G[u].push_back(v);
     99         }
    100         find_scc();
    101         for (int u = 0; u < n; u++)
    102         {
    103             for (auto v : G[u])
    104             {
    105                 if (sccno[v] != sccno[u])
    106                 {
    107                     out[sccno[u]]++;
    108                     in[sccno[v]]++;
    109                 }
    110             }
    111         }
    112         int a = 0, b = 0;
    113         for (int i = 1; i <= scc_cnt; i++)
    114         {
    115             if (!out[i])
    116                 a++;
    117             if (!in[i])
    118                 b++;
    119         }
    120         int ans = max(a, b);
    121         if (scc_cnt == 1)
    122             ans = 0;
    123         cout << ans << endl;
    124     }
    125     return 0;
    126 }
  • 相关阅读:
    oracle中查询表中先排序再取出前10条数据
    oracle中的数据类型
    读取Oracle中的clob字段
    实现json的序列化和反序列化
    在oracle中where 子句和having子句中的区别
    Oracle Clob字段保存时提示字符串过长
    读取文件夹中的文件并修改数据库中的数据
    【转】display:none与visible:hidden的区别
    实现http访问
    动态生成并执行SQL语句
  • 原文地址:https://www.cnblogs.com/npugen/p/10751166.html
Copyright © 2011-2022 走看看