2017年多校赛第九场 1006 Senior Pan(dijkstra套路题)

来源:互联网 发布:淘宝满包邮在哪里设置 编辑:程序博客网 时间:2024/06/07 12:49

点击打开链接

这道题有很多解法,我是按照题解的做法写了一遍。

题意:给出一个有向图,然后有k个点,问这k个点两两之间的最短距离的最小值是多少。

解法:题解是把k个点按照每个点二进制位的不同分成两个集合,然后求一次多源最短路。由于最大的数是1e5,所以也就到个。。。2^17的样子?由于是有向图,还需要正反都跑一遍。所以一共跑34次最短路就出来了。。。

代码如下:

#include<iostream>#include<cstdio>#include<vector>#include<queue>#include<utility>#include<stack>#include<algorithm>#include<cstring>#include<string>#include<cmath>#include<set>#include<map>using namespace std;typedef pair<long long, int> pii;const int maxn = 1e5 + 5;const int maxm = 2e5 + 5;const long long INF = 1e18;int a[maxn];int head[maxn], to[maxm], nx[maxm], cost[maxm], ppp = 0;void add_edge(int u, int v, int val) {    to[ppp] = v, nx[ppp] = head[u], cost[ppp] = val, head[u] = ppp++;}priority_queue <pii, vector<pii>, greater<pii> > q;long long dis[maxn];void dijkstra() {    while(!q.empty()) {        pii tmp = q.top();        q.pop();        int u = tmp.second;        if(dis[u] < tmp.first)            continue;        for(int i = head[u]; ~i; i = nx[i]) {            int v = to[i];            if(dis[v] > dis[u] + cost[i]) {                dis[v] = dis[u] + cost[i];                q.push(pii(dis[v], v));            }        }    }}int main() {#ifndef ONLINE_JUDGE    freopen("in.txt", "r", stdin);//    freopen("out.txt", "w", stdout);#endif    int T, Case = 1;    scanf("%d", &T);    while(T--) {        memset(head, -1, sizeof(head));        ppp = 0;        int n, m;        scanf("%d%d", &n, &m);        while(m--) {            int u, v, c;            scanf("%d%d%d", &u, &v, &c);            add_edge(u, v, c);        }        int k;        scanf("%d", &k);        for(int i = 0; i < k; i++) {            scanf("%d", &a[i]);        }        int ind = 1;        long long Min = 1e18;        while(1) {            int cnt = 0;            fill(dis, dis + n + 1, INF);            for(int i = 0; i < k; i++) {                if(a[i] & ind) {                    dis[a[i]] = 0;                    q.push(pii(0, a[i]));                    cnt++;                }            }            if(cnt == 0)                break;            dijkstra();            for(int i = 0; i < k; i++) {                if(a[i] & ind)                    continue;                if(Min > dis[a[i]])                    Min = dis[a[i]];            }                        fill(dis, dis + n + 1, INF);            for(int i = 0; i < k; i++) {                if(!(a[i] & ind)) {                    dis[a[i]] = 0;                    q.push(pii(0, a[i]));                    cnt++;                }            }            dijkstra();            for(int i = 0; i < k; i++) {                if(!(a[i] & ind))                    continue;                if(Min > dis[a[i]])                    Min = dis[a[i]];            }                        ind <<= 1;        }        printf("Case #%d: %lld\n", Case++, Min);    }    return 0;}


原创粉丝点击