zoukankan      html  css  js  c++  java
  • hdu6041

    hdu6041

    题意

    给出一个仙人掌

    如果一个无向连通图的任意一条边最多属于一个简单环,我们就称之为仙人掌。所谓简单环即不经过重复的结点的环。

    求前 (K) 小生成树 。

    分析

    仙人掌中每个环中我们最多可以删掉一条边,题目就变成了有 (M) 个数组,每次从每个数组中分别取一个数字并求和,前 (K) 大的和。

    首先用 (Tarjan) 算法找环,然后使用优先队列不断合并两个数组( 多路归并问题,见白书 P189 )。

    code

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int MAXN = 1e5 + 10;
    const int M = 2e3;
    int n, m, K;
    struct Edge {
        int to, w, next;  
    }e[M << 1];
    int cnt, head[M << 1];
    void addedge(int u, int v, int w) {
        e[cnt].to = v;
        e[cnt].w = w;
        e[cnt].next = head[u];
        head[u] = cnt++;
    }
    int a[MAXN], b[MAXN], c[MAXN];
    int dfn[M], sz;
    stack<int> sta;
    struct Item {
        int s;
        int x;
        Item(int s, int x):s(s), x(x) {}
        bool operator<(const Item& other) const {
            return s < other.s;
        }
    };
    void cal() {
        priority_queue<Item> q;
        for(int i = 1; i <= b[0]; i++) {
            q.push(Item(a[1] + b[i], 2));
        }
        c[0] = 0;
        while(c[0] < K && !q.empty()) {
            Item it = q.top(); q.pop();
            c[++c[0]] = it.s; 
            if(it.x <= a[0]) q.push(Item(it.s - a[it.x - 1] + a[it.x], it.x + 1));
        }
        a[0] = c[0];
        for(int i = 1; i <= c[0]; i++) {
            a[i] = c[i];
        }
    }
    int tarjan(int fa, int u) {
        dfn[u] = ++sz;
        int lowu = sz;
        for(int i = head[u]; ~i; i = e[i].next) {
            int v = e[i].to;
            if(!dfn[v]) {
                sta.push(i);
                int lowv = tarjan(u, v);
                if(lowu <= lowv) {
                    b[0] = 0;
                    while(1) {
                        int j = sta.top(); sta.pop();
                        b[++b[0]] = e[j].w;
                        if(j == i) break;
                    }
                    if(b[0] > 1) cal();
                } else lowu = lowv;
            } else if(v != fa && lowu > dfn[v]) {
                sta.push(i);
                lowu = dfn[v];
            }
        }
        return lowu;
    }
    int main() {
        int kase = 1;
        while(~scanf("%d%d", &n, &m)) {
            while(!sta.empty()) sta.pop();
            cnt = 0;
            sz = 0;
            memset(dfn, 0, sizeof dfn);
            memset(head, -1, sizeof head);
            a[0] = 1; a[1] = 0;
            int s = 0;
            for(int i = 0; i < m; i++) {
                int u, v, w;
                scanf("%d%d%d", &u, &v, &w);
                s += w;
                addedge(u, v, w); 
                addedge(v, u, w);
            }
            scanf("%d", &K);
            tarjan(-1, 1);
            unsigned ans = 0;
            for(int i = 1; i <= a[0]; i++) {
                ans = ans + (unsigned)i * (s - a[i]);
            }         
            if(a[0] == 0) ans = s;
            printf("Case #%d: %u
    ", kase++, ans);
        }   
        return 0;
    }
    
  • 相关阅读:
    Windows 8.1 应用开发 – 触控操作
    Windows Phone App Studio 无码开发手机应用
    尝试HTML + JavaScript 编写Windows App
    Ubuntu远程连接MySQL(connection refused)解决方法
    [MySQL]查看用户权限与GRANT用法
    mysql 创建用户命令-grant
    搭建memcached使用:/usr/bin/phpize 安装memcached扩展的时候报错
    在linux中使用phpize安装php扩展模块
    跟锦数学全部资料
    33套2020数分高代试题参考解答[2020/04/14更新,更多请关注跟锦数学微信公众号]
  • 原文地址:https://www.cnblogs.com/ftae/p/7260507.html
Copyright © 2011-2022 走看看