[hdu5521 Meeting]最短路

 

题意:有N个点,给定M个集合,集合Si里面的点两两之间的距离都为Ti,集合里面的所有点数之和<=1e6。有两个人分别在1和N处,求1个点使得两个人到这一点距离的最大值最小

思路:这题是裸的最短路问题,难点在建图。然而建图也只有1步,在集合外新建1个点,每个点向它连一条Ti/2的边(避免浮点数,可以先乘2,然后结果除以2)。如此巧妙。。。

#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define pb(x) push_back(x)
#define mp(x, y) make_pair(x, y)
#define all(a) (a).begin(), (a).end()
#define mset(a, x) memset(a, x, sizeof(a))
#define mcpy(a, b) memcpy(a, b, sizeof(b))
#define cas() int T, cas = 0; cin >> T; while (T --)
template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}
template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}
typedef long long ll;
typedef pair<int, int> pii;

#ifndef ONLINE_JUDGE
    #include "local.h"
#endif

const int N = 1e6 + 7;

struct Edge {
    int u, v, w;
    int next;
    Edge(int u, int v, int w) {
        this->u = u;
        this->v = v;
        this->w = w;
    }
    Edge() {}
};
int SZ;
int head[N];
Edge edge[N << 1];
ll d1[N], dn[N];
int n, m, nn;
bool used[N];

void add(int u, int v, int w) {
    edge[SZ] = Edge(u, v, w);
    edge[SZ].next = head[u];
    head[u] = SZ ++;
}

void spfa(int s, ll d[]) {
    queue<int> Q;
    for (int i = 1; i <= nn; i ++) d[i] = pow(10, 18) + 7;
    d[s] = 0;
    mset(used, 0);
    Q.push(s);
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        used[u] = false;
        for (int i = head[u]; ~i; i = edge[i].next) {
            Edge e = edge[i];
            if (umin(d[e.v], d[u] + e.w)) {
                if (!used[e.v]) {
                    Q.push(e.v);
                    used[e.v] = true;
                }
            }
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    int t, s, u;
    cas() {
        printf("Case #%d: ", ++ cas);
        cin >> n >> m;
        nn = n;
        mset(head, -1);
        SZ = 0;
        for (int i = 0; i < m; i ++) {
            scanf("%d%d", &t, &s);
            nn ++;
            for (int j = 0; j < s; j ++) {
                scanf("%d", &u);
                add(u, nn, t);
                add(nn, u, t);
            }
        }
        spfa(1, d1);
        spfa(n, dn);
        ll mind = pow(10, 18);
        bool yes = false;
        vector<int> ans;
        for (int i = 1; i <= n; i ++) {
            if (umin(mind, max(d1[i], dn[i]))) yes = true;
        }
        if (!yes) {
            puts("Evil John");
            continue;
        }
        cout << mind / 2 << endl;
        for (int i = 1; i <= n; i ++) {
            if (max(d1[i], dn[i]) == mind) {
                ans.pb(i);
            }
        }
        sort(all(ans));
        for (int i = 0; i < ans.size(); i ++) {
            printf("%d%c", ans[i], i == ans.size() - 1? '\n' : ' ');
        }
    }
    return 0;
}

  

posted @ 2015-10-31 21:26  jklongint  阅读(809)  评论(0编辑  收藏  举报