码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5521 Meeting 最短路

时间:2016-06-08 00:15:42      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

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

题意;

给你一副图,n个节点,一个人在1,一个人在n问你在哪个节点相遇花的时间最短。

题解:

比较快想到的思路就是起点,终点都跑一遍最短路。

但是发现边太多,图建不出来。

重新构造一幅等价的图可以解决这道题:

为每一个集合建一个新节点,属于某个集合的节点,建一条权值为0的边到代表这个集合的新节点,同时新节点向属于这个集合的节点建一条权值为w(w为这个集合任意两点的距离)的边。

然后跑两次最短路。

证明:

属于集合的点到集合的距离自然为0,而集合到点的距离则表示着从该集合的另一个点到达这个点,所以距离为w。

代码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#include<queue>
#define X first
#define Y second
#define mp make_pair
using namespace std;

const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;

int n, m;
vector<pair<int,int> > G[maxn];

int d1[maxn], d2[maxn],dd[maxn];
int inq[maxn];
int ans;
void spfa(int s,int *d) {
    memset(inq, 0, sizeof(inq));
    memset(d, 0x7f, sizeof(int)*maxn);
    queue<int> Q;
    Q.push(s), d[s] = 0, inq[s] = 1;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        inq[u] = 0;
        for (int i = 0; i < G[u].size(); i++) {
            int v = G[u][i].X, w = G[u][i].Y;
            if (d[v] > d[u] + w) {
                d[v] = d[u] + w;
                if (!inq[v]) {
                    inq[v] = 1, Q.push(v);
                }
            }
        }
    }
}


void init() {
    ans = INF;
    for (int i = 0; i < n + m; i++) G[i].clear();
}

int main() {
    int tc,kase=0;
    scanf("%d", &tc);
    while (tc--) {
        scanf("%d%d", &n, &m);
        init();
        for (int i = 0; i < m; i++) {
            int w, cnt,v;
            scanf("%d%d", &w, &cnt);
            for (int j = 0; j < cnt; j++) {
                scanf("%d", &v); v--;
                G[i + n].push_back(mp(v, w));
                G[v].push_back(mp(i + n, 0));
            }
        }
        spfa(0, d1);
        spfa(n - 1, d2);
        for (int i = 0; i < n; i++) {
            dd[i] = max(d1[i], d2[i]);
            ans = min(ans, dd[i]);
        }
        vector<int> vec;
        for (int i = 0; i < n; i++) if (dd[i] == ans) {
            vec.push_back(i + 1);
        }
        printf("Case #%d: ", ++kase);
        if (ans == INF) {
            printf("Evil John\n");
        }
        else {
            printf("%d\n", ans);
            for (int i = 0; i < vec.size() - 1; i++) printf("%d ", vec[i]);
            printf("%d\n", vec[vec.size() - 1]);
        }
    }
    return 0;
}

 

HDU 5521 Meeting 最短路

标签:

原文地址:http://www.cnblogs.com/fenice/p/5568706.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!