标签:
每个点向他所在集合连一条权为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