zoukankan      html  css  js  c++  java
  • HDU 1827 Summer Holiday(强连通分量,贪心)

    题目链接

    解题思路

      题目要求需要联系的最少人数和最小花费。先求出图中所有的连通分量,然后把他们都缩成一个点,这个点的花费就是同一连通分量中的最小的花费。对于缩点之后的图,找出所有入度为0的点开始就行了,为什么呢?因为没有点能够到达入度为0的点,所以对于每一个这样的点都需要访问一次。

    代码

    const int maxn = 1e4+10;
    struct {
        int to, nex;
    } e[maxn<<1];
    int h[maxn], ecnt;
    void ae(int u, int v) {
        e[ecnt].to = v;
        e[ecnt].nex = h[u];
        h[u] = ecnt++;
    }
    int dfn[maxn], dfncnt; 
    int low[maxn]; 
    int sk[maxn], tp; 
    int scc[maxn], sc; 
    int cost[maxn], minc[maxn], in[maxn];
    void tarjan(int u) {
        sk[++tp] = u;
        low[u] = dfn[u] = ++dfncnt; 
        for (int i = h[u]; i; i = e[i].nex) {
            int v = e[i].to;
            if (!dfn[v]) { 
                tarjan(v);
                low[u] = min(low[u], low[v]);
            }
            else if (!scc[v]) 
                low[u] = min(low[u], dfn[v]);
        }
        if (dfn[u]==low[u]) {
            ++sc;
            while(true) { 
                int v = sk[tp--];
                scc[v] = sc;
                if (u==v) break;
            }
        }
        return;
    }
    int main() {
        int n, m, u, v;
        while(~scanf("%d%d", &n, &m)) {
            for (int i = 1; i<=n; ++i) {
                dfn[i] = low[i] = scc[i] = in[i] = 0;
                minc[i] = INF;
            }
            dfncnt = tp = sc = 0; ecnt = 1;
            for (int i = 1; i<=n; ++i) scanf("%d", &cost[i]);
            for (int i = 0; i<m; ++i) {
                scanf("%d%d", &u, &v);
                ae(u, v);
            }
            for (int i = 1; i<=n; ++i) if (!dfn[i]) tarjan(i);
            for (int i = 1; i<=n; ++i)
                minc[scc[i]] = min(minc[scc[i]], cost[i]);
            for (int i = 1; i<=n; ++i)
                for (int j = h[i]; j; j=e[j].nex)
                    if (scc[i]!=scc[e[j].to]) in[scc[e[j].to]] = 1;
            int ans = 0, num = 0;
            for (int i = 1; i<=sc; ++i)
                if (!in[i]) {
                    ++num;
                    ans += minc[i];
                }
            printf("%d %d
    ", num, ans);
        }
        return 0;
    }
    
  • 相关阅读:
    JavaScript 正则表达式上——基本语法
    温故知新 javascript 正则表达式
    Js把IE COM数组列表转换成数组
    Linux用户和用户组管理总结
    Linux FTP 服务器配置简单说明
    Linux中Samba详细安装
    js本地存储解决方案(localStorage与userData)
    通过了解渲染过程来提高页面性能
    使用Chrome DevTools的Timeline和Profiles提高Web应用程序的性能
    内存泄漏,循环引用
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12877743.html
Copyright © 2011-2022 走看看