调了一晚上的题qwq。。。%%%zxy原创题啊tql%%%
先说说最短路,由于出题人极为毒瘤,他既卡了SPFA又卡了堆优化的dij(反正我也没写qwq堆优化只有10pts来着?),考虑一个点可能被多次松弛,所以堆里可能会有许多无用状态,所以只要卡卡这个堆的大小高度就会让一次操作的复杂度接近n但不满,所以考虑一个稳定复杂度的算法就是用set去代替堆。
然后考虑答案的统计。
不在最短路上的边,断了也不会对答案有影响,所以直接输出最短路长即可。
然后就是在最短路上的边,很明显不会枚举断边跑最短路,所以就有一个很有用的东西出来了:最短路树。
最短路树是基于原图建立的一棵树,以s为根,这棵树保证从父亲到儿子的路径权值和为父亲到儿子的最短路长度。反之从儿子到父亲亦然。但如果两者的lca不是两者中的一个的话就不满足这个性质。
显然,如果我们建出这样的一棵树,那么s->t的这条链上的任意边被删都会对答案有影响。
最优解的构造一定是这样的:s->u->v->t,其中u->v为非断边,s->u的最短路显然可以直接在最短路树上找到,但问题在于如何保证v->t,或者说t->v是最短路。
显然如果v是t的祖先的话可以直接在最短路树上找到,但如果不是,那么可以证明,t到v的最短路一定不会经过当前处理子树的连向父亲的边,因为如果经过再返回的的话就违背了最短路树的性质(因为爷爷到孙子的距离一定大于爸爸到孙子的距离)。
所以对于一条非树边u->v,其中u属于t所在连通块,v属于s所在连通块,将他的权值更新为disT[u]+w[i]+disS[v],那么假设当前处理的点为u,如果断掉u->fa[u]这条边,那么答案就变为set中维护的最小值。
(可能意识模糊的在口胡。。。如果有错请指出)
#include
using namespace std;
const int MAXN=1e5+10;
const int MAXM=5e5+10;
const int INF=0x3f3f3f3f;
int n,m,cnt=1,s,t;
int head[MAXN],disS[MAXN],disT[MAXN],vis[MAXN];
int nxt[MAXM],to[MAXM],w[MAXM];
int tedge[MAXM],fa[MAXN],dfn[MAXN],ys[MAXN],tot;
int pre[MAXN],ban[MAXN];
int ans[MAXM],in[MAXN],ins[MAXM];
int sta[MAXN],top;
struct Edge{
int to,id;
};
vector graph[MAXN];
set > se;
int Read(){
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
void add(int x,int y,int z){
cnt++;
nxt[cnt]=head[x];
head[x]=cnt;
to[cnt]=y;
w[cnt]=z;
}
void dijkstra1(){
memset(disS,INF,sizeof(disS));
disS[s]=0;
set >q;
q.insert(make_pair(0,s));
while(!q.empty()){
int u=q.begin()->second;
q.erase(q.begin());
if(vis[u])
continue;
for(int i=head[u];i!=-1;i=nxt[i]){
int v=to[i];
if(disS[v]>disS[u]+w[i]){
q.erase(make_pair(disS[v],v));
disS[v]=disS[u]+w[i];
q.insert(make_pair(disS[v],v));
}
}
}
}
void dijkstra2(){
memset(disT,INF,sizeof(disT));
disT[t]=0;
set >q;
q.insert(make_pair(0,t));
while(!q.empty()){
int u=q.begin()->second;
q.erase(q.begin());
for(int i=head[u];i!=-1;i=nxt[i]){
int v=to[i];
if(disT[v]>disT[u]+w[i]){
q.erase(make_pair(disT[v],v));
disT[v]=disT[u]+w[i];
q.insert(make_pair(disT[v],v));
}
}
}
}
void dfs1(int u,int f){
vis[u]=1;
dfn[u]=++tot;
ys[tot]=u;
fa[u]=f;
for(int i=head[u];i!=-1;i=nxt[i]){
int v=to[i];
if(vis[v]||v==f)
continue;
if(disS[v]==disS[u]+w[i]){
dfs1(v,u);
tedge[i>>1]=1;
pre[v]=i>>1;
graph[u].push_back((Edge){v,i>>1});
}
}
}
void dfs2(int u){
sta[++top]=u;
ban[u]=1;
int siz=graph[u].size();
for(int i=0;i1;--i){
int u=ys[i];
if(in[u]){
in[fa[u]]=1;
top=0,dfs2(u);
for(int j=1;j<=top;++j){
int p=sta[j];
for(int x=head[p];x!=-1;x=nxt[x]){
int v=to[x];
if(tedge[x>>1])
continue;
if(ban[v]){
if(ins[x>>1])
se.erase(make_pair(disS[p]+w[x]+disT[v],x>>1));
}
else{
se.insert(make_pair(disT[p]+w[x]+disS[v],x>>1));
ins[x>>1]=1;
}
}
}
ans[pre[u]]=se.empty()?-1:se.begin()->first;
}
else{
ans[pre[u]]=disS[t];
}
}
}
int main(){
memset(head,-1,sizeof(head));
n=Read(),m=Read();
s=1,t=n;
for(int i=1;i<=m;++i){
int x=Read(),y=Read(),z=Read();
add(x,y,z),add(y,x,z);
}
dijkstra1();
dijkstra2();
if(disS[t]==INF){
for(int i=1;i<=m;++i)
puts("-1");
return 0;
}
dfs1(s,-1);
solve();
for(int i=1;i<=m;++i)
cout<