bzoj4289
最短路
很容易想到边和边之间连边,但是这样菊花图就完蛋了
我们想办法优化一下,能不能不要每条边都连。
考虑查分,把一个点的出边串起来,这样就行了,每条无向边拆成两条就能保证了
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5 + 5; namespace IO { const int Maxlen = N * 50; char buf[Maxlen], *C = buf; int Len; inline void read_in() { Len = fread(C, 1, Maxlen, stdin); buf[Len] = '\0'; } inline void fread(int &x) { x = 0; int f = 1; while (*C < '0' || '9' < *C) { if(*C == '-') f = -1; ++C; } while ('0' <= *C && *C <= '9') x = (x << 1) + (x << 3) + *C - '0', ++C; x *= f; } inline void fread(long long &x) { x = 0; long long f = 1; while (*C < '0' || '9' < *C) { if(*C == '-') f = -1; ++C; } while ('0' <= *C && *C <= '9') x = (x << 1) + (x << 3) + *C - '0', ++C; x *= f; } inline void read(int &x) { x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + c - '0'; c = getchar(); } x *= f; } inline void read(long long &x) { x = 0; long long f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 1ll) + (x << 3ll) + c - '0'; c = getchar(); } x *= f; } } using namespace IO; int rd() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x * f; } int n, cnt = 1, source, sink, m; int head[N], hd[N * 8], st[N], vis[N * 8]; ll d[N * 8]; struct edge { int nxt, to, w; } e[N * 8]; bool cmp(int i, int j) { return e[i].w < e[j].w; } void link(int *head, int u, int v, int w) { e[++cnt].nxt = head[u]; head[u] = cnt; e[cnt].to = v; e[cnt].w = w; } int main() { read_in(); fread(n); fread(m); for(int i = 1; i <= m; ++i) { int u, v, w; fread(u); fread(v); fread(w); link(head, u, v, w); link(head, v, u, w); } source = 0; sink = 6 * m + 1; for(int i = 1; i <= n; ++i) { int top = 0; for(int j = head[i]; j; j = e[j].nxt) st[++top] = j; sort(st + 1, st + top + 1, cmp); for(int j = 1; j <= top; ++j) { int now = st[j], nxt = st[j + 1]; if(i == 1) link(hd, source, now, e[now].w); if(e[now].to == n) link(hd, now, sink, e[now].w); link(hd, now, now ^ 1, e[now].w); if(j < top) { link(hd, now, nxt, e[nxt].w - e[now].w); link(hd, nxt, now, 0); } } } priority_queue<pair<ll, int>, vector<pair<ll, int> >, greater<pair<ll, int> > > q; memset(d, 0x3f3f, sizeof(d)); d[source] = 0; q.push({0, source}); while(!q.empty()) { pair<ll, int> o = q.top(); q.pop(); int u = o.second; if(vis[u]) continue; vis[u] = 1; for(int i = hd[u]; i; i = e[i].nxt) if(d[e[i].to] > d[u] + e[i].w) { d[e[i].to] = d[u] + e[i].w; q.push({d[e[i].to], e[i].to}); } } printf("%lld\n", d[sink]); return 0; }