1 条题解
-
0
自动搬运
来自洛谷,原作者为

wzporz
**搬运于
2025-08-24 21:22:13,当前版本为作者最后更新于2018-07-21 18:15:50,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
暂时运行效率rank1,大概是因为没有信仰,以为过不了1000,所以写了个。
容易发现这题是一张稠密图,所以用的即可,所谓的堆优化其实是劣化。关于SPFA,虽然这里没有死,但是已经死了。
是某道题目的简化版:做法一样。
首先我们进行一次dijkstra,得到点1到点n的最短路径(如果有多条,随便找一条)。
显然,如果移除的不是这条路径上的边,贡献是不变的,现在考虑如果移除这条路径上的边。
那么对于另外的某一条路径,可以去update这条路径上的一些边
如果最短路径是A->B->...->C->D,存在一条路径A->B->E->C->D,那么在B->...->C这一段路径上的所有边如果去掉,还有那条路经,所以可以更新。
那么转化成一个简单的问题:区间取min,最后求所有值。
这个直接线段树区间取min(标记永久化),最后dfs一遍得到所有路径上删掉之后的max(还可以排序之后并查集维护)
注意这里的我们维护的对于1~n最短路径上的每条边,删掉它之后的1到n的最短距离。
来口胡一下证明,显然如果一条边跨越显然是对的,因为这条边一定可以正确地更新答案。
如果有超过一条边跨越,这条链与1到n最短路径的相连的点一定是直接走最短路径最优(不会劣),那么中间一定有一条边一定有路径1->这条路径->n,显然不重复。
#include<bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; typedef long long ll; #define gc getchar #define Rep(i,a,b) for(register int i=(a);i<=int(b);++i) #define Dep(i,a,b) for(register int i=(a);i>=int(b);--i) #define rep(i,a,b) for(register int i=(a);i<int(b);++i) inline ll read(){ register ll x=0,f=1;register char c=gc(); for(;!isdigit(c);c=gc())if(c=='-')f=-1; for(;isdigit(c);c=gc())x=(x<<1)+(x<<3)+(c^48); return x*f; } #define pc putchar void write(ll x){if(x<0)x=-x,pc('-');if(x>=10)write(x/10);putchar(x%10+'0');} void writeln(ll x){write(x);puts("");} const int maxn = 1005; bool vis[maxn]; int d1[maxn],dn[maxn],pre[maxn]; int n,m; int a[maxn][maxn]; void dijkstra(int S,int dist[]){ Rep(i,1,n) vis[i] = false; Rep(i,1,n) dist[i] = inf; dist[S] = 0;pre[S]=0; Rep(i,1,n){ int k = -1; Rep(j,1,n){ if(vis[j]) continue; if(k == -1 || dist[k] > dist[j]) k = j; } vis[k] = true; Rep(j,1,n){ if(vis[j]) continue; if(dist[j] > dist[k] + a[k][j]){ dist[j] = dist[k] + a[k][j]; pre[j] = k; } } } } vector<int> edge[maxn]; int fa[maxn]; int mx,pos[maxn]; inline int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);} #define lson (o<<1) #define rson ((o<<1|1)) int tag[maxn<<2]; void modify(int o,int l,int r,int x,int y,int v){ if(l==x&&r==y){tag[o] = min(tag[o],v);return ;} int mid = (l + r) >> 1; if(y<=mid) modify(lson,l,mid,x,y,v); else if(mid+1<=x)modify(rson,mid+1,r,x,y,v); else{ modify(lson,l,mid,x,mid,v); modify(rson,mid+1,r,mid+1,y,v); } } void build(int o,int l,int r){ tag[o]=inf; if(l==r)return; int mid = (l+r)>>1; build(lson,l,mid);build(rson,mid+1,r); } int query(int o,int l,int r,int x){ if(l==r) return tag[o]; int mid = (l+r)>>1; if(x<=mid) return min(query(lson,l,mid,x),tag[o]); else return min(query(rson,mid+1,r,x),tag[o]); } int main(){ n = read(),m = read(); Rep(i,1,n)Rep(j,1,n) a[i][j] = inf; Rep(i,1,m){ int x = read(),y = read(),v = read(); a[x][y] = a[y][x] = v; } dijkstra(n,dn); dijkstra(1,d1); Rep(i,1,n) fa[i] = pre[i]; mx = 0; for(int i=n;i;i=pre[i]){ pos[i] = ++mx; fa[i] = i; if(pre[i]) a[i][pre[i]] = a[pre[i]][i] = inf; } build(1,1,n); Rep(i,1,n){ Rep(j,1,n){ if(i==j) continue; if(a[i][j] != inf){ int w = min(dn[i] + d1[j] + a[i][j],dn[j]+d1[i]+a[i][j]); int x = pos[find(i)],y = pos[find(j)]; if(x>y)swap(x,y); if(x==y) continue; modify(1,1,mx,x+1,y,w); } } } int ans = d1[n]; Rep(i,2,n) ans = max(ans,query(1,1,mx,i)); writeln(ans); }
- 1
信息
- ID
- 187
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者