标签:
每个点向他所在集合连一条权为0的边,每个集合向他里面所有点连一条权为c的边,跑最短路就行了.
#include <bits/stdc++.h> using namespace std; #define prt(k) cerr<<#k" = "<<k<<endl typedef long long LL; //const int inf = 0x3f3f3f3f; const int M = 2000100; const LL inf = 0x3f3f3f3f3f3f3f3fLL; struct Edge { int v; int w; int nxt; Edge() {} Edge(int vv, int ww, int Nxt = -1) { v = vv , w = ww, nxt = Nxt; } } e[M << 2]; int head[M], mm; void initEdge() { mm = 0; memset(head, -1, sizeof head); } void adde(int u, int v, int w) { swap(u, v); e[mm] = Edge(v, w, head[u]); head[u] = mm ++; } vector<int> g[M]; int n, m; LL d1[ M], d2[ M]; struct Heap { LL d; int u; Heap() {} Heap(LL dd, int uu) { d = dd, u = uu; } bool operator < (const Heap& rhs) const { return d > rhs.d; } }; bool done[M]; void Dij(int src, LL d[]) { priority_queue<Heap> Q; memset(d, 0x3f, sizeof d); for (auto x: g[src]) { d[x + n] = 0; Q.push(Heap(0, x + n)); } Q.push(Heap(0, src)); d[src] = 0; memset(done, false, sizeof done); while (!Q.empty()) { Heap x = Q.top(); Q.pop(); int u = x.u; if (done[u]) continue; done[u] = true; for (int i=head[u];~i;i=e[i].nxt) { LL w = e[i].w; int v = e[i].v; if (d[v] > d[u] + w) { d[v] = d[u] + w; Q.push(Heap(d[v], v)); } } } } int main() { int re, ca=1; scanf("%d", &re); while (re-- ) { scanf("%d%d", &n, &m); initEdge(); for (int i=1;i<=n;i++) g[i].clear(); for (int i=1;i<=m;i++) { int cost, k; scanf("%d%d", &cost, &k); while (k -- ) { int x; scanf("%d", &x); adde(i + n, x, cost); g[x].push_back(i); } } for (int i=1;i<=n;i++) for (int j : g[i]) adde(i, j+n, 0); memset(d1, 0x3f, sizeof d1); memset(d2, 0x3f, sizeof d2); Dij(1, d1); Dij(n, d2); LL ans = inf; for (int i=1;i<=n;i++) { ans = min(ans, max(d1[i], d2[i])); } vector<int> vec; printf("Case #%d: ", ca++); if (ans >= inf) { puts("Evil John"); continue; } printf("%I64d\n", ans); for (int i=1;i<=n;i++) if (ans == max(d1[i], d2[i])) { vec.push_back(i); } for (int i=0;i<vec.size();i++) printf("%d%c", vec[i], i==vec.size()-1 ? 10 : ‘ ‘); } }
标签:
原文地址:http://www.cnblogs.com/oilover/p/4926231.html