• HDU 6166


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

    题意:给你一幅有向图,选取 K 个点,k 个点任意二点做最短路,输出最小值。

    题解:根据k个点某一位上的二进制是 0 或是 1 ,分为二个集合,一个集合为源点,另一个集合为汇点。

         最小值其实就是 k 个点中某二个点的最短路,将这二个点分别放入一个集合,剩余的 k-2 个点放任意集合即可。

         根据某一位上的二进制划分,可以将任意二点分开。

       多源多汇点求最短路。由于二进制的位数最多 20 位,所以做 20 次dijkstra即可。

       由于这是有向图,分点的时候源点、汇点调换一下。

         这里的边用链式向前星存储,dijkstra用优先队列优化。

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<queue> 
    #define oo 0x3f3f3f3f 
    using namespace std;
    const int MAXN = 100000+10;
    struct node
    {
        int b, e, w;
        int next;
    }edge[MAXN];
    struct no
    {
        int e, w;
        no(){
        }
        no(int e, int w):e(e), w(w){
        }
        bool operator < (const no aa)const
        {
            return w > aa.w;
        }
    };
    int head[MAXN];
    int a[MAXN];
    bool ise[MAXN];
    int grap[MAXN];
    priority_queue<no> que;
    int dij()
    {
        while(!que.empty())
        {
            no nod = que.top();
            que.pop();
            if(ise[nod.e]) return nod.w;
            for(int i = head[nod.e]; ~i; i = edge[i].next)
            {
                if(grap[edge[i].e] > grap[nod.e] + edge[i].w)
                {
                    grap[edge[i].e] = grap[nod.e] + edge[i].w;
                    que.push( no(edge[i].e, grap[edge[i].e]) );
                }
            }
        }
        return oo;
    }
    void addedge(int x, int y, int z, int i)
    {
        edge[i].b = x;
        edge[i].e = y;
        edge[i].w = z;
        edge[i].next = head[x];
        head[x] = i;
    }
    void init()
    {
        memset(ise, false, sizeof(ise));
        memset(grap, oo, sizeof(grap));
        while(!que.empty()) que.pop();
    }
    int main (void)
    {
        ios::sync_with_stdio(false);
        int t; cin >> t;
        int Case = 0;
        while(t--)
        {
            int n, m;
            cin >> n >> m;
            memset(head, 0xffff, sizeof(head));
            for(int i = 1; i <= m; i++)
            {
                int x, y, z;
                cin >> x >> y >> z;
                addedge(x, y, z, i);
            }
            int k; cin >> k;
            for(int i = 1; i <= k; i++)
            {
                cin >> a[i];
            }
            int ans = oo;
            for(int j = 0; j <= 20; j++ )
            {
                init();
                for(int i = 1; i <= k; i++)
                {
                    if(a[i]&(1<<j))
                    {
                        ise[a[i]] = true; 
                    }
                    else
                    {
                        que.push(no(a[i], 0));
                        grap[a[i]] = 0; 
                    }
                }
                ans = min(ans, dij());
                
                init();
                for(int i = 1; i <= k; i++)
                {
                    if(a[i]&(1<<j))
                    {
                        que.push(no(a[i], 0));
                        grap[a[i]] = 0; 
                    }
                    else
                    { 
                        ise[a[i]] = true; 
                    }
                }
                ans = min(ans, dij());
            }
            cout << "Case #" << ++Case << ": " << ans << endl;
        }
    }
    /*
    1
    2 1
    1 2 1
    2
    1 2
    */
  • 相关阅读:
    [LintCode] Flatten Nested List Iterator 压平嵌套链表迭代器
    [LintCode] Reverse Pairs 翻转对
    [CareerCup] 17.9 Word Frequency in a Book 书中单词频率
    [CareerCup] 17.8 Contiguous Sequence with Largest Sum 连续子序列之和最大
    [CareerCup] 17.7 English Phrase Describe Integer 英文单词表示数字
    [LeetCode] Reverse Vowels of a String 翻转字符串中的元音字母
    [CareerCup] 17.6 Sort Array 排列数组
    [LeetCode] 344. Reverse String 翻转字符串
    [CareerCup] 17.5 Game of Master Mind 猜字游戏
    [CareerCup] 17.4 Maximum of Two Numbers 两数中的较大值
  • 原文地址:https://www.cnblogs.com/lkcc/p/7436246.html
Copyright © 2020-2023  润新知