题意:
给你一个n个结点m条边的有负权边无负环的有向图,为每条边赋一个非负新值,在新图上的u到v的最短路上的点和原图上最短路上的点相同且顺序不变。

思路:
参考了多篇题解,我们造一个超级源点与每一个点相连,且边权为0,从超级源点开始跑spfa;
我们这m条边的新值为d[u]-d[v]+cost(u,v);
证明:
spfa松弛的条件是d[u]+cost(u,v)<d[v],所以d[u]+cost(u,v)-d[v]>=0;
如果新图有一条路为u-x1-x2-v。
则路的距离为d[u]+cost(u,x1)-d[x1]+d[x1]+cost(x1,x2)-d[x2]+d[x2]+cost(x2,v)-d[v]。
化简为:d[u]-d[v]+cost(u,x1)+cost(x1,x2)+cost(x2,v)。
又因为对于d[u]和d[v]是固定的,所以与原图最短路相同且顺序不变。

代码:

#include <bits/stdc++.h>

#define inf 1000000007
#define eps 0.00000001
using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int maxn=100005;

inline int read()
{
    char c=getchar();
    int f=1, x=0;
    while(c>'9'||c<'0')
    {
        if(c=='-')
        {
            f=-1;
        }
        c=getchar();
    }
    while(c<='9'&&c>='0')
    {
        x=(x<<3)+(x<<1)+(c^48);
        c=getchar();
    }
    return f*x;
}

struct w
{
    int to, cost;
}w;

struct edge
{
    int u, v, w;
}edge[10005];

vector<struct w> g[10005];

int d[10005], use[10005];

void spfa()
{
   int p=0;
   fill(d,d+10005,inf);
   queue<int> q;
   q.push(p);
   d[0]=0;
   //printf("asd");
   while(!q.empty())
   {
       p=q.front();
       q.pop();
       int v=p;
       use[v]=0;
       for(int i=0;i<g[v].size();i++)
       {
           if(d[v]+g[v][i].cost<d[g[v][i].to])
           {
               d[g[v][i].to]=d[v]+g[v][i].cost;
               if(use[g[v][i].to]==0)
               {
                   p=g[v][i].to;
                   use[g[v][i].to]=1;
                   q.push(p);
               }
           }
       }
   }
}

int main()
{
    int n, m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int u, v, t;
        scanf("%d%d%d",&u,&v,&t);
        edge[i].u=u;
        edge[i].v=v;
        edge[i].w=t;
        w.to=v;
        w.cost=t;
        g[u].push_back(w);
    }
    w.cost=0;
    for(int i=1;i<=n;i++)
    {
        w.to=i;
        g[0].push_back(w);
    }
    spfa();
    for(int i=0;i<m;i++)
    {
        printf("%d %d %d\n",edge[i].u,edge[i].v,d[edge[i].u]-d[edge[i].v]+edge[i].w);
    }
    return 0;
}