zoukankan      html  css  js  c++  java
  • hdu6166 Senior Pan

    Senior Pan

    Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
    Total Submission(s): 1411    Accepted Submission(s): 558

    Problem Description
    Senior Pan fails in his discrete math exam again. So he asks Master ZKC to give him graph theory problems everyday.
    The task is simple : ZKC will give Pan a directed graph every time, and selects some nodes from that graph, you can calculate the minimum distance of every pair of nodes chosen in these nodes and now ZKC only cares about the minimum among them. That is still too hard for poor Pan, so he asks you for help.
    Input
    The first line contains one integer T, represents the number of Test Cases.1≤T≤5.Then T Test Cases, for each Test Cases, the first line contains two integers n,m representing the number of nodes and the number of edges.1≤n,m≤100000
    Then m lines follow. Each line contains three integers xi,yi representing an edge, and vi representing its length.1≤xi,yi≤n,1≤vi≤100000
    Then one line contains one integer K, the number of nodes that Master Dong selects out.1≤K≤n
    The following line contains K unique integers ai, the nodes that Master Dong selects out.1≤ai≤n,ai!=aj
    Output
    For every Test Case, output one integer: the answer
    Sample Input
    1 5 6 1 2 1 2 3 3 3 1 3 2 5 1 2 4 2 4 3 1 3 1 3 5
    Sample Output
    Case #1: 2
    Source
    题目大意:给定一个n个点m条边的有向带权图,其中有k个特殊点,求这k个特殊点之间两两最短路的最小值。
    分析:没做过这类题根本想不到.
       因为是求两两最短路的最小值,可以考虑把dijkstra变成多源的,也就是把这k个特殊点分成两组,一组当作源点,一组当作汇点,因为dijkstra算法每次找距离最小的出来扩展嘛,那么作为源点的一组最先被扩展到的距离就是这次dijkstra算法应该返回的答案.
       但是怎样分组才能不遗漏的计算完呢?
       考虑一种神奇的分组方式--二进制分组.将k个点的编号转化成二进制数.如果第i位1则当作源点,否则当作汇点,然后交换两组再来一次dijkstra.这样一定会考虑所有的组合方式.why?两个不同的编号,必然在二进制上有一位不同.这一位的不同将它们分成两组计算,所以每一组都计算到了,取个min就是答案.
       我认为分类方法可能还有很多,不遗漏是关键.这道题如果能想到把dijkstra变成多源的就基本上做完了.
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    const int maxn = 100010;
    const ll inf = 1e17;
    
    int T,cas,n,vis[maxn],m,head[maxn],to[maxn],nextt[maxn],w[maxn],tot = 1,K,a[maxn],mark[maxn];
    ll d[maxn],ans = inf;
    
    struct node
    {
        int x;
        ll len;
        bool operator < (const node& a) const {
            return len > a.len;
        }
    };
    priority_queue<node> q;
    
    void add(int x,int y,int z)
    {
        w[tot] = z;
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    ll dijkstra()
    {
        while (!q.empty())
        {
            node u = q.top();
            q.pop();
            int x = u.x;
            ll len = u.len;
            if (mark[x])
                return len;
            if (vis[x])
                continue;
            vis[x] = 1;
            for (int i = head[x];i;i = nextt[i])
            {
                int v = to[i];
                if (d[v] > d[x] + w[i])
                {
                    d[v] = d[x] + w[i];
                    node temp;
                    temp.x = v;
                    temp.len = d[v];
                    q.push(temp);
                }
            }
        }
        return inf;
    }
    
    void solve()
    {
        for (int i = 0; i < 20; i++)
        {
            while (!q.empty())
                q.pop();
            memset(vis,0,sizeof(vis));
            memset(mark,0,sizeof(mark));
            memset(d,127/3,sizeof(d));
            for (int j = 1; j <= K; j++)
            {
                if ((1 << i) & a[j])
                    mark[a[j]] = 1;
                else
                {
                    node temp;
                    temp.x = a[j];
                    temp.len = 0;
                    d[a[j]] = 0;
                    q.push(temp);
                }
            }
            ans = min(ans,dijkstra());
            memset(vis,0,sizeof(vis));
            memset(mark,0,sizeof(mark));
            memset(d,127/3,sizeof(d));
            while (!q.empty())
                q.pop();
            for (int j = 1; j <= K; j++)
            {
                if ((1 << i) & a[j])
                {
                    node temp;
                    temp.len = 0;
                    temp.x = a[j];
                    d[a[j]] = 0;
                    q.push(temp);
                }
                else
                    mark[a[j]] = 1;
            }
            ans = min(ans,dijkstra());
        }
    }
    
    int main()
    {
        scanf("%d",&T);
        while (T--)
        {
            ans = inf;
            tot = 1;
            memset(head,0,sizeof(head));
            scanf("%d%d",&n,&m);
            for (int i = 1; i <= m; i++)
            {
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                add(x,y,z);
            }
            scanf("%d",&K);
            for(int i = 1; i <= K; i++)
                scanf("%d",&a[i]);
            solve();
            printf("Case #%d: %lld
    ",++cas,ans);
        }
    
        return 0;
    }
  • 相关阅读:
    Hadoop--单点故障修复
    Hadoop---静动态增删节点
    sqlserver 通知应用程序(存储过程通过http调用接口)
    sqlserver 资源等待
    sqlserver 性能优化
    sqlserver 资源等待
    sqlserver 查看内存情况
    sqlserver动态管理视图
    常见散列算法
    sqlserver 性能检测 和 监控
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8448376.html
Copyright © 2011-2022 走看看