題意:ios
給一張 n 個點,m 條邊的無向圖,要求設定一些邊的邊權
使得全部邊權都是正整數,最終 S 到 T 的最短路爲 Lspa
1 ≤ n ≤ 1000, 1 ≤ m ≤ 10000code
spfa求s到t最短路且知足可變邊最少ci
而後把不在最短路上的可變邊標爲inf,最短路上的可變邊修改爲使最短路長爲Lget
其餘的賦值爲inf只是保證了通過其餘可變邊的路徑不會更短,沒有保證不通過其餘可變邊只是少通過了幾條可變邊、致使比最短路長的路徑不會在最短路修改後更短string
存在繞過某條可變邊的路徑p,原本不是最短路且不通過最短路上可變邊x,但你修改x以後,p會變成當前最短路,因而這個作法就掛掉了。it
就是說走了非可變邊,把你修改的那條可變邊繞過去了io
應當選擇知足d<L的路徑中通過可變邊最少的一條class
能夠在最短路上加維,\(d(i,j)\)表示1到i通過j條可變邊的最短路test
複雜度\(O(mn\log{mn})\)
隨便求一條最短路,一樣其餘賦值inf,而後枚舉最短路上的可變邊,依次修改改可變邊的值,修改後再求最短路看看會不會被繞過去。最後必定會收斂出答案
無解:不通過可變邊就能夠<L,通過可變邊也比L大
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> #include <vector> using namespace std; typedef long long ll; const int N = 1e5+5, M = 1e6+5; const ll inf = 1e16; int n, m, L, s, t; struct edge {int u, v, ne; ll w;} e[M]; struct meow {int u, v; ll w;} a[M]; int cnt=1, h[N], mark[M]; inline void ins(int u, int v, ll w) { if(w == 0) w=1, mark[cnt+1] = mark[cnt+2] = 1; e[++cnt] = (edge) {u, v, h[u], w}; h[u] = cnt; e[++cnt] = (edge) {v, u, h[v], w}; h[v] = cnt; a[cnt>>1] = (meow) {u, v, w}; } inline void paint(int x, ll v) { a[x].w = v; e[x<<1].w = e[x<<1|1].w = v; } ll d[N]; int inq[N], pre[N]; int q[N], head, tail; inline void lop(int &x) {if(x==N) x = 1;} void spfa0(int s) { memset(d, 0x3f, sizeof(d)); head = tail = 1; d[s] = 0; q[tail++] = s; inq[s] = 1; while(head != tail) { int u = q[head++]; lop(head); inq[u] = 0; for(int i=h[u]; i; i=e[i].ne) if(!mark[i]) { int v = e[i].v; if(d[v] > d[u] + e[i].w) { d[v] = d[u] + e[i].w; if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1; } } } } void spfa(int s) { memset(d, 0x3f, sizeof(d)); memset(inq, 0, sizeof(inq)); head = tail = 1; d[s] = 0; q[tail++] = s; inq[s] = 1; while(head != tail) { int u = q[head++]; lop(head); inq[u] = 0; for(int i=h[u]; i; i=e[i].ne) { int v = e[i].v; if(d[v] > d[u] + e[i].w ) { d[v] = d[u] + e[i].w; pre[v] = i; if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1; } } } } int chose[N]; vector<int> li; int main() { //freopen("in", "r", stdin); ios::sync_with_stdio(false); cin.tie(); cout.tie(); cin >> n >> m >> L >> s >> t; s++; t++; for(int i=1; i<=m; i++) { int u, v, w; cin >> u >> v >> w; u++; v++; ins(u, v, w); } spfa0(s); if(d[t] < L) {cout << "NO"; return 0;} spfa(s); if(d[t] > L) {cout << "NO"; return 0;} if(d[t] == L) { cout << "YES" << endl; for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n'; return 0; } int x = t; while(x != s) { if(mark[pre[x]]) chose[pre[x]>>1] = 1, li.push_back(pre[x]>>1); x = e[pre[x]].u; } for(int i=1; i<=cnt>>1; i++) if(mark[i<<1] && !chose[i]) paint(i, inf); for(int i=0; i<li.size(); i++) { int now = li[i]; int delta = L - d[t] + 1; paint(now, delta); spfa(s); if(d[t] == L) break; } cout << "YES" << endl; for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n'; }
ps:假作法的代碼
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; typedef long long ll; const int N = 1e5+5, M = 1e6+5; const ll inf = 1e16; int n, m, L, s, t; struct edge {int u, v, ne; ll w;} e[M]; struct meow {int u, v; ll w;} a[M]; int cnt=1, h[N], mark[M]; inline void ins(int u, int v, ll w) { if(w == 0) w=1, mark[cnt+1] = mark[cnt+2] = 1; e[++cnt] = (edge) {u, v, h[u], w}; h[u] = cnt; e[++cnt] = (edge) {v, u, h[v], w}; h[v] = cnt; a[cnt>>1] = (meow) {u, v, w}; } ll d[N]; int inq[N], cou[N], pre[N]; int q[N], head, tail; inline void lop(int &x) {if(x==N) x = 1;} void spfa0(int s) { memset(d, 0x3f, sizeof(d)); head = tail = 1; d[s] = 0; q[tail++] = s; inq[s] = 1; while(head != tail) { int u = q[head++]; lop(head); inq[u] = 0; for(int i=h[u]; i; i=e[i].ne) if(!mark[i]) { int v = e[i].v; if(d[v] > d[u] + e[i].w) { d[v] = d[u] + e[i].w; if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1; } } } } namespace test { int pre[N]; void spfa1(int s) { memset(d, 0x3f, sizeof(d)); head = tail = 1; d[s] = 0; q[tail++] = s; inq[s] = 1; while(head != tail) { int u = q[head++]; lop(head); inq[u] = 0; for(int i=h[u]; i; i=e[i].ne) { int v = e[i].v; if(d[v] > d[u] + e[i].w) { d[v] = d[u] + e[i].w; pre[v] = i; if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1; } } } } } void spfa(int s) { memset(d, 0x3f, sizeof(d)); memset(cou, 0x3f, sizeof(cou)); memset(inq, 0, sizeof(inq)); head = tail = 1; d[s] = 0; cou[s] = 0; q[tail++] = s; inq[s] = 1; while(head != tail) { int u = q[head++]; lop(head); inq[u] = 0; for(int i=h[u]; i; i=e[i].ne) { int v = e[i].v; if(d[v] > d[u] + e[i].w || (d[v] == d[u]+e[i].w && cou[v] > cou[u] + mark[i])) { d[v] = d[u] + e[i].w; cou[v] = cou[u] + mark[i]; pre[v] = i; if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1; } } } } int chose[N]; int main() { //freopen("in", "r", stdin); ios::sync_with_stdio(false); cin.tie(); cout.tie(); cin >> n >> m >> L >> s >> t; s++; t++; for(int i=1; i<=m; i++) { int u, v, w; cin >> u >> v >> w; u++; v++; ins(u, v, w); } spfa0(s); if(d[t] < L) {cout << "NO"; return 0;} spfa(s); if(d[t] > L) {cout << "NO"; return 0;} if(d[t] == L) { cout << "YES" << endl; for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n'; return 0; } int x = t; int flag = 0; while(x != s) { if(mark[pre[x]]) chose[pre[x]>>1] = 1, flag = pre[x] >> 1; x = e[pre[x]].u; } if(!flag) {cout << "NO"; return 0;} for(int i=1; i <= cnt>>1; i++) if(mark[i<<1] && !chose[i]) a[i].w = inf; for(int i=1; i<=cnt; i++) if(mark[i] && !chose[i>>1]) e[i].w = inf; int delta = L - d[t] + 1; a[flag].w = delta; e[flag<<1].w = e[flag<<1|1].w = delta; test::spfa1(s); if(d[t] != L) { cout << d[t] << "nooooo\n"; int x = t; while(x != s) { if(test::pre[x] != pre[x]) { cout << "wrong\n"; cout << mark[pre[x]] << " " << mark[test::pre[x]] << '\n'; } x = e[pre[x]].u; } } cout << "YES" << endl; for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '\n'; }