CodeForces 715 B.Complete The Graph(Dijkstra)

时间:2023-02-03 09:16:03

Description
一个n个点m条边的无向图,每条边有正边权,0边权表示可以修改该条边的边权为任意正整数,给出起点s和终点t,问是否有一种修改边权的方案使得s到t的最短路为L
Input
第一行五个整数n,m,L,s,t分别表示点数,边数,要求的最短路的长度,起点和终点,之后m行每行三个整数u,v,c表示u和v之间有一条权值为c的边,如果c=0表示该条边的边权可以被修改(2<=n<=1000,1<=m<=10000,1<=L<=1e9,0<=s,t<=n-1,s!=t)
Output
如果存在一个满足条件的方案则输出YES以及每条边的边权,否则输出NO
Sample Input
5 5 13 0 4
0 1 5
2 1 2
3 2 3
1 4 0
4 3 4
Sample Output
YES
0 1 5
2 1 2
3 2 3
1 4 8
4 3 4
Solution
首先对除去可修改边的图以s为起点跑一遍最短路,如果dis[t] < L,说明不论如何修改可修改边的边权,最终dis[t]必然小于L,无解;如果dis[t]>=L,则一条条的加入可修改边看是否可以缩短s到t的最短路,因为边权必须是正整数,所以初始边权设为最小值1,跑完最短路后如果dis[t] < L,那么说明该条边在最短路径上,那么把该条边边权设为L-(dis[t]-1)就可以使dis[t]变成L了,在处理完所有的可修改边后,如果dis[t]还是大于L则无解,否则有解
Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define maxn 1111
#define maxm 11111
typedef pair<int,int>P;//first是最短距离,second是顶点编号 
struct edge
{
    int to,cost;
};
int n,m,L,s,t;
vector<edge>g[maxn];//邻接矩阵 
ll dis[maxn];//dis[i]表示i到s的最短距离 
void init(int n)//初始化 
{
    for(int i=0;i<n;i++)g[i].clear();
}
void add(int u,int v,int c)//单向边,从u到v,权值为c 
{
    g[u].push_back((edge){v,c});
} 
void Dijkstra(int s)//求所有顶点到起点s的最短距离 
{
    priority_queue< P,vector<P>,greater<P> >que;//堆按照first从大到小的顺序取出值 
    for(int i=0;i<n;i++)dis[i]=1e18;
    dis[s]=0;
    que.push(P(0,s));//起点进队 
    while(!que.empty())
    {
        P p=que.top();
        que.pop();
        int v=p.second;
        if(dis[v]<p.first) continue;//剪枝 
        for(int i=0;i<g[v].size();i++)
        {
            edge e=g[v][i];
            if(dis[e.to]>dis[v]+e.cost)
            {
                dis[e.to]=dis[v]+e.cost;
                que.push(P(dis[e.to],e.to));
            }
        }
    }
}
int e[maxm][3];
int main()
{
    scanf("%d%d%d%d%d",&n,&m,&L,&s,&t); 
    init(n);
    for(int i=0;i<m;i++)
    {
        int u,v,c;
        scanf("%d%d%d",&u,&v,&c);
        if(c)add(u,v,c),add(v,u,c);
        e[i][0]=u,e[i][1]=v,e[i][2]=c;
    }
    Dijkstra(s);
    if(dis[t]<L)printf("NO\n");
    else
    {
        for(int i=0;i<m;i++)
        {
            int u=e[i][0],v=e[i][1],c=e[i][2];
            if(c)continue;
            add(u,v,1),add(v,u,1);
            e[i][2]=1;
            Dijkstra(s);
            if(dis[t]<L)
            {
                e[i][2]=L-dis[t]+1;
                g[u][g[u].size()-1].cost=e[i][2];
                g[v][g[v].size()-1].cost=e[i][2];
            }
        }
        if(dis[t]>L)printf("NO\n");
        else
        {
            printf("YES\n");
            for(int i=0;i<m;i++)printf("%d %d %d\n",e[i][0],e[i][1],e[i][2]);
        }
    }
    return 0;
}