版权声明:虽然我很菜,不过转载请标明出处。 https://blog.csdn.net/Patrickpwq/article/details/86629729
萌新冒泡
首先有个套路 只要题目中说了源点到每个点最短路径是唯一的 那往往都和最短路树有关系
题意是求不能经过最后一条边的次短路 要使得这条路最短 显然要尽量的多走最短路径上的路
假设现在要求1->x 我们考虑走了一段最短路径后如何跳到x点
设当前点为u 选择与u点相连的一条非树边(这条边连向x的子树内的某点v) 然后ans[x]=dis[u]+w(u,v)+(dis[v]-dis[x])
然后我们就可以暴力枚举每条非树边暴力更新啦!
仔细观察发现 对于每条非树边 dis[u]+w(u,v)+dis[v]是个定值
wow 那把这个值算出来 排个序 似乎还是要扫一遍?不过如果强烈安利并查集——可以维护哪些点已经被修改过了,因为被修改过的点肯定是连续的
然后好像卡SPFA是出题人的基本素养
#include<bits/stdc++.h>
const int N=100005;
const int M=200005;
const int INF=0x3f3f3f3f;
using namespace std;
int n,m;
struct Edge
{
int from,to,next,val;
}edge[2*M];
int first[N],tot;
inline void addedge(int x,int y,int z)
{
tot++;
edge[tot].from=x; edge[tot].to=y; edge[tot].next=first[x]; edge[tot].val=z; first[x]=tot;
}
typedef pair<int,int> Pair;
priority_queue<Pair,vector<Pair>,greater<Pair> > heap;
int dis[N],father[N];
bool done[N];
void Dijkstra()
{
memset(dis,0x3f,sizeof(dis));
memset(done,0,sizeof(done));
dis[1]=0; heap.push(make_pair(0,1)); father[1]=0;
while(!heap.empty())
{
int now=heap.top().second;
heap.pop();
if(done[now]) continue;
done[now]=1;
for(int u=first[now];u;u=edge[u].next)
{
int vis=edge[u].to;
if(dis[now]+edge[u].val<dis[vis])
{
dis[vis]=dis[now]+edge[u].val;
father[vis]=now;
heap.push(make_pair(dis[vis],vis));
}
}
}
}
struct Tree
{
int val,from,to;
bool operator <(const Tree &p) const
{
return this->val<p.val;
}
}tree[M];
int fa[N],ans[N];
inline int getfather(int x)
{
if(fa[x]==x) return x;
fa[x]=getfather(fa[x]);
return fa[x];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin>>n>>m;
for(int i=1,x,y,z;i<=m;i++)
{
cin>>x>>y>>z;
addedge(x,y,z); addedge(y,x,z);
}
Dijkstra();
// for(int i=1;i<=n;i++) cout<<father[i]<<endl;
int cnt=0;
for(int i=1,x,y;i<=tot;i+=2)
{
x=edge[i].from; y=edge[i].to;
if(father[x]==y||father[y]==x) continue;
//非树边
tree[++cnt].val=dis[x]+dis[y]+edge[i].val;
tree[cnt].from=x;
tree[cnt].to=y;
}
sort(tree+1,tree+cnt+1);
for(int i=1;i<=n;i++) fa[i]=i;
memset(ans,-1,sizeof(ans));
for(int i=1,x,y;i<=cnt;i++)
{
x=getfather(tree[i].from); y=getfather(tree[i].to);
while(x!=y)
{
if(dis[x]<dis[y]) swap(x,y); //默认x更深
ans[x]=tree[i].val-dis[x];
fa[x]=father[x];
x=getfather(x);
}
}
for(int i=2;i<=n;i++) cout<<ans[i]<<endl;
return 0;
}