zoukankan      html  css  js  c++  java
  • Hdu 2767 把森林变成强连通分量.cpp

    题意:

      给出n个点和他们之间的一些关系..

      问加多少条边可以使所有的点变成强连通分量..

     

    思路:

      根据题意就可以知道有这个推理:

        原图缩点后的有向无环图..

        出度为0的点和入度为0的点中个数少的那些点向个数多的那些点连线..

        可以使森林变成强连通分量..

     

    Tips:

      注意如果缩点后变成一个点了..

      则入度为0和出度为0的点的个数都是1 但是实际上已经是强连通分量..不需要连线了..

      所以答案应该是0

     

    Code:

    View Code
      1 #include <stdio.h>
      2 #include <cstring>
      3 #include <algorithm>
      4 using namespace std;
      5 const int INF = 0x1f1f1f1f;
      6 #define clr(x) memset(x, 0, sizeof(x))
      7 const int MAXN = 20010;
      8 
      9 struct Edge
     10 {
     11     int to;
     12     int next;
     13 }edge[10000010];
     14 int head[MAXN];
     15 int tot;
     16 
     17 void add(int s, int u)
     18 {
     19     edge[tot].to = u;
     20     edge[tot].next = head[s];
     21     head[s] = tot++;
     22 }
     23 
     24 int dfn[MAXN], low[MAXN];
     25 int ins[MAXN], sta[MAXN], col[MAXN];
     26 int ti, top, cnt;
     27 int n;
     28 
     29 void tarjan(int u)
     30 {
     31     int i, k;
     32     dfn[u] = low[u] = ++ti;
     33     ins[u] = 1;
     34     sta[++top] = u;
     35     for(i = head[u]; i != -1; i = edge[i].next) {
     36         k = edge[i].to;
     37         if(dfn[k] == 0) {
     38             tarjan(k);
     39             low[u] = min(low[u], low[k]);
     40         } else if(ins[k]) {
     41             low[u] = min(low[u], dfn[k]);
     42         }
     43     }
     44     if(dfn[u] == low[u]) {
     45         cnt++;
     46         do
     47         {
     48             k = sta[top--];
     49             col[k] = cnt;
     50             ins[k] = 0;
     51         }while(u != k);
     52     }
     53 
     54 }
     55 
     56 void solve_ta()
     57 {
     58     int i, k;
     59     ti = top = cnt = 0;
     60     clr(dfn);
     61     for(i = 1; i <= n; ++i)
     62         if(!dfn[i])
     63             tarjan(i);
     64 }
     65 
     66 int ans;
     67 int in[MAXN], out[MAXN];
     68 void solve()
     69 {
     70     int i, j, k;
     71     ans = 0;
     72     clr(in), clr(out);
     73     solve_ta();
     74 
     75     for(i = 1; i <= n; ++i) {
     76         for(j = head[i]; j != -1; j = edge[j].next) {
     77             k = edge[j].to;
     78             if(col[i] != col[k]) {
     79                 in[col[k]]++;
     80                 out[col[i]]++;
     81             }
     82         }
     83     }
     84 
     85     int tmpa = 0, tmpb = 0;
     86     for(i = 1; i <= cnt; ++i) {
     87         if(in[i] == 0) tmpa++;
     88         if(out[i] == 0) tmpb++;
     89     }
     90 
     91     ans = max(tmpa, tmpb);
     92     if(cnt == 1) ans = 0;
     93 }
     94 
     95 int main()
     96 {
     97     int i, j, k;
     98     int a, b, T, m;
     99     scanf("%d", &T);
    100     while(T--)
    101     {
    102         tot = 0;
    103         memset(head, 0xff, sizeof(head));
    104 
    105         scanf("%d %d", &n, &m);
    106         while(m--) {
    107             scanf("%d %d", &a, &b);
    108             add(a, b);
    109         }
    110         solve();
    111         printf("%d\n", ans);
    112     }
    113     return 0;
    114 }

     

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2767

  • 相关阅读:
    使用递归遍历目录
    Isseck 定位文件流
    二:C标准库文件I/O函数
    IPC进程通信
    操作系统知识总结
    Makefile简单使用
    人际交往
    AIX ksh补全命令
    java.lang.IllegalArgumentException: Wildcard string cannot be null or empty.
    WEB项目实现QQ在线推广功能
  • 原文地址:https://www.cnblogs.com/Griselda/p/2711779.html
Copyright © 2011-2022 走看看