• hdu6166


    hdu6166

    题意

    给出一个有向图,选择 (k) 个点,问这 (k) 个点任意两点距离的最小值。

    分析

    按结点编号的二进制位,每次可以把所有点分到两个集合,那么求两个集合的点间的最短路即可( (0)作为源点,(n+1)作为汇点)。

    正确性的保证:编号的唯一性。任意两点一定存在某一次不在同一集合,二进制位一定有某一位不同。

    code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int, ll> P;
    const int MAXN = 1e5 + 10;
    const ll INF = 1e18 + 9;
    int n, m;
    struct node {
        int to, cost;
        node() {}
        node(int to, int cost) : to(to), cost(cost) {}
    };
    vector<node> G[MAXN];
    ll d[MAXN];
    ll dijkstra() {
        fill(d, d + MAXN, INF);
        priority_queue<P, vector<P>, greater<P> > q;
        d[0] = 0;
        q.push(P(0, 0));
        while(!q.empty()) {
            P u = q.top(); q.pop();
            if(d[u.second] < u.first) continue;
            for(int i = 0; i < G[u.second].size(); i++) {
                node nd = G[u.second][i];
                if(d[nd.to] > d[u.second] + nd.cost) {
                    d[nd.to] = d[u.second] + nd.cost;
                    q.push(P(d[nd.to], nd.to));
                }
            }
        }
        return d[n + 1];
    }
    int se[MAXN];
    int main() {
        int T, kase = 1;
        scanf("%d", &T);
        while(T--) {
            for(int i = 0; i <= n; i++) G[i].clear();
            scanf("%d%d", &n, &m);
            for(int i = 0; i < m; i++) {
                int u, v, c;
                scanf("%d%d%d", &u, &v, &c);
                G[u].push_back(node(v, c));
            }
            int k;
            scanf("%d", &k);
            for(int i = 0; i < k; i++) {
                scanf("%d", &se[i]);
            }
            ll ans = INF;
            for(int i = 0; i < 18; i++) {
                G[0].clear();
                for(int j = 0; j < k; j++) {
                    if((se[j] >> i) & 1) {
                        G[0].push_back(node(se[j], 0));
                    } else {
                        G[se[j]].push_back(node(n + 1, 0));
                    }
                }
                ans = min(ans, dijkstra());
                for(int j = 0; j < k; j++) {
                    if(!((se[j] >> i) & 1)) {
                        G[se[j]].pop_back();
                    }
                }
                G[0].clear();
                for(int j = 0; j < k; j++) {
                    if((se[j] >> i) & 1) {
                        G[se[j]].push_back(node(n + 1, 0));
                    } else {
                        G[0].push_back(node(se[j], 0));
                    }
                }
                ans = min(ans, dijkstra());
                for(int j = 0; j < k; j++) {
                    if((se[j] >> i) & 1) {
                        G[se[j]].pop_back();
                    }
                }
            }
            printf("Case #%d: %lld
    ", kase++, ans);
        }
        return 0;
    }
    
  • 相关阅读:
    正则表达式(四)--文本换行分割
    java加密类型和算法名称
    记事本记录日志
    DNS
    jstl--c:choose标签
    csv文本编辑引号问题
    JDBC----ReflectionUtils
    Jsp
    计算机网络 编程 总结:
    N颗骰子的问题
  • 原文地址:https://www.cnblogs.com/ftae/p/7430094.html
Copyright © 2020-2023  润新知