题意: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'; }