hdu-6166 Senior Pan

来源:互联网 发布:下载单机游戏的软件 编辑:程序博客网 时间:2024/06/05 22:50

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
2017 Multi-University Training Contest - Team 9

题意:n个点, m条边, k个点的集合, 求这个集合中所有点对的最短路的最小值。
题解:nm都在1e5, 暴力枚举肯定超时, 可以把k个点分为两个集合, A集合和B集合, A集合的点与超级源点相连, B集合的点与超级汇点相连,距离为0, 跑一边最短路就是A点到B点的最短路的最小值了。然后可以枚举每一位的二进制,为0就放入A, 为1就放入B, 因为每个点不相同, 所以每对点都会至少一次放入不同的AB两个集合, 最多只用跑16遍最短路就好。
还有一种思路是随机化, 随机每个点在哪个集合, 因为答案只可能是两个点产生的, 所以最短的那条路的起点和终点都是固定的,每次随机,起点在正确的集合的概率为1/2,终点在正确的集合的概率为1/2,每次随机的概率即为1/4, 只用随机20次左右,每次取最小的就是答案。错误的概率就为(3/4)^20 ≈ 0.003 相信大家的人品不会差到交一次会wa的地步吧哈哈哈。

写的比较丑, 所以时间很长。
代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int MaxN = 100000;struct node{    int v, w, next;}e[MaxN * 10 + 1];struct Node{    long long d;    int x;    bool operator < (const Node p) const    {        return d > p.d;    }};int g[MaxN + 1], cnt;int n, m;int uu[MaxN + 1], vv[MaxN + 1], ww[MaxN + 1];int a[MaxN + 1];void addedge(int u, int v, int w){    e[cnt].v = v;    e[cnt].w = w;    e[cnt].next = g[u];    g[u] = cnt++;}long long dijkstra(){    long long dist[MaxN + 1];    for (int i = 1; i <= n + 1; i++)        dist[i] = 1e12;    dist[0] = 0;    priority_queue<Node> q;    Node t;    t.x = 0, t.d = 0;    q.push(t);    while (!q.empty())    {        Node cur = q.top();        q.pop();        for (int i = g[cur.x]; i != -1; i = e[i].next)        {            int v = e[i].v;            if (dist[v] > cur.d + e[i].w)            {                dist[v] = cur.d + e[i].w;                Node t;                t.x = v;                t.d = dist[v];                q.push(t);            }        }    }    return dist[n + 1];}int main(){    int T, cas = 0;    scanf("%d", &T);    while (T--)    {        scanf("%d %d", &n, &m);        for (int i = 1; i <= m; i++)            scanf("%d %d %d", &uu[i], &vv[i], &ww[i]);        int Q;        scanf("%d", &Q);        for (int i = 1; i <= Q; i++)            scanf("%d", &a[i]);        int S = 0, T = n + 1;        long long ans = 1e12;        for (int j = 0; j <= 16; j++)        {            memset(g, -1, sizeof(g));            cnt = 0;            for (int i = 1; i <= m; i++)                addedge(uu[i], vv[i], ww[i]);            for (int i = 1; i <= Q; i++)            {                if (a[i] & (1 << j))                    addedge(S, a[i], 0);                else                    addedge(a[i], T, 0);            }            ans = min(dijkstra(), ans);            memset(g, -1, sizeof(g));            cnt = 0;            for (int i = 1; i <= m; i++)                addedge(uu[i], vv[i], ww[i]);            for (int i = 1; i <= Q; i++)            {                if (a[i] & (1 << j))                    addedge(a[i], T, 0);                else                    addedge(S, a[i], 0);            }            ans = min(dijkstra(), ans);        }        printf("Case #%d: %lld\n", ++cas, ans);    }    return 0;}
原创粉丝点击