zoukankan      html  css  js  c++  java
  • HDU 1827:Summer Holiday(强连通)

    http://acm.hdu.edu.cn/showproblem.php?pid=1827

    思路:强连通分量缩点后找入度为0的点,然后对于属于该强连通分量的找一个最小耗费的入口。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <iostream>
      5 #include <queue>
      6 #include <cmath>
      7 #include <map>
      8 #include <vector>
      9 #include <stack>
     10 using namespace std;
     11 #define N 80010
     12 #define M 30010
     13 #define INF 0x3f3f3f3f
     14 struct node
     15 {
     16     int u, v, next;
     17 }edge[N*2];
     18 stack<int> sta;
     19 int tot, cnt, num, head[N], belong[N], dfn[N], low[N], n, m, a[N], in[N], mi[N];
     20 bool vis[N];
     21 
     22 void init()
     23 {
     24     tot = cnt = num = 0;
     25     while(sta.size()) sta.pop();
     26     memset(head, -1, sizeof(head));
     27     memset(belong, 0, sizeof(belong));
     28     memset(dfn, 0, sizeof(dfn));
     29     memset(low, 0, sizeof(low));
     30     memset(vis, false, sizeof(vis));
     31     memset(in, 0, sizeof(in));
     32     memset(mi, INF, sizeof(mi));
     33 }
     34 
     35 void add(int u, int v)
     36 {
     37     edge[tot].u = u; edge[tot].v = v; edge[tot].next = head[u]; head[u] = tot++;
     38 }
     39 
     40 void tarjan(int u)
     41 {
     42     vis[u] = 1;
     43     sta.push(u);
     44     dfn[u] = low[u] = ++cnt;
     45     for(int i = head[u]; ~i; i = edge[i].next) {
     46         int v = edge[i].v;
     47         if(!dfn[v]) {
     48             tarjan(v);
     49             if(low[v] < low[u]) low[u] = low[v];
     50         } else if(vis[v]) {
     51             if(dfn[v] < low[u]) low[u] = dfn[v];
     52         }
     53     }
     54     if(dfn[u] == low[u]) {
     55         ++num;
     56         int top = -1;
     57         while(top != u) {
     58             top = sta.top(); sta.pop();
     59             belong[top] = num;
     60             vis[top] = 0;
     61         }
     62     }
     63 }
     64 
     65 int main()
     66 {
     67     while(~scanf("%d%d", &n, &m)) {
     68         init();
     69         for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
     70         for(int i = 0; i < m; i++) {
     71             int u, v;
     72             scanf("%d%d", &u, &v);
     73             add(u, v);
     74         }
     75         for(int i = 1; i <= n; i++)
     76             if(!dfn[i]) tarjan(i);
     77         for(int u = 1; u <= n; u++) {
     78             for(int i = head[u]; ~i; i = edge[i].next) {
     79                 int v = edge[i].v;
     80                 if(belong[u] != belong[v]) { //缩点后找入度为0的点
     81                     in[belong[v]]++;
     82                 }
     83             }
     84         }
     85         int ans = 0, sum = 0;
     86         for(int i = 1; i <= num; i++) {
     87             if(!in[i]) {
     88                 ans++;
     89                 for(int j = 1; j <= n; j++) {
     90                     if(belong[j] == i) {
     91                         if(a[j] < mi[i]) {
     92                             mi[i] = a[j]; //对于不同的强连通分量之间找耗费最小的入口
     93                         }
     94                     }
     95                 }
     96                 sum += mi[i];
     97             }
     98         }
     99         printf("%d %d
    ", ans, sum);
    100     }
    101     return 0;
    102 }
    103 
    104 /*
    105 4 3
    106 1 2 3 4
    107 1 2
    108 1 3
    109 1 4
    110 */
  • 相关阅读:
    常用的一些js方法
    git常用命令
    thread join和detach的区别
    C和C++的区别和联系
    C++面试集锦( 面试被问到的问题 )
    C/C++面试题:编写类String的构造函数、析构函数和赋值函数。
    C++ 多态的实现及原理
    获取当前操作系统的ip
    CString的头文件
    C++ 多用户模式下同一个exe只能运行一次
  • 原文地址:https://www.cnblogs.com/fightfordream/p/5929270.html
Copyright © 2011-2022 走看看