CF716D Complete The Graph

图论+构造

首先可以发现如果去除了可以改变权值的边,$s$到$t$的最短路若小于$l$,那么一定不行

若等于则直接将可改边权的边改为inf,输出即可

那么现在原图中的最短路是大于$l$的

因为每一条边是都要加入图中的,而且每条边边权至少为1

那么可以不断向图中加入权值为1的边,并且在加边的过程中不断跑最短路

如果加完当前的边,$s$到$t$的最短路小于l的话,将这条边权值增加

剩下的边边权改为inf即可

简单证明这种做法

首先考虑加入1边后,最短路依然大于$l$,那么继续使最短路减小

再考虑加入1边后,最短路小于$l$

因为在加入这条边之前最短路大于l,那么加入这条边后,最短路肯定经过这条边

而增加边权之后,最短路还是比之前的小,那么最短依然经过这条边

不会出现增加了这条边的边权之后,最短路不经过这条边的情况

那么得到的图最短路必定为l

#include <bits/stdc++.h>
#define ll long long
#define inf (ll)1e17;
using namespace std;
const int MAXN=20100;
int n,m,l,s,t,tot;
int first[1100],nxt[MAXN],point[MAXN];
int vi[1100];
ll d[1100],len[MAXN];
struct node
{
    int u,v;
    ll l;
}sh[MAXN];
void add_edge(int x,int y,int z)
{
    tot++;
    nxt[tot]=first[x];
    first[x]=tot;
    point[tot]=y;
    len[tot]=z;
}
void spfa()//最短路
{
    queue <int> q;
    for (int i=0;i<n;i++)
      d[i]=inf;
    d[s]=0;
    vi[s]=1;
    q.push(s);
    while (!q.empty())
    {
        int f;
        f=q.front();
        q.pop();
        vi[f]=0;
        for (int i=first[f];i!=-1;i=nxt[i])
        {
            int u;
            u=point[i];
            if (d[u]>d[f]+len[i])
            {
                d[u]=d[f]+len[i];
                if (!vi[u])
                {
                    vi[u]=1;
                    q.push(u);
                }
            }
        }
    }
}
int main()
{
    tot=-1;
    memset(first,-1,sizeof(first));
    memset(nxt,-1,sizeof(nxt));
    scanf("%d%d%d%d%d",&n,&m,&l,&s,&t);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%lld",&sh[i].u,&sh[i].v,&sh[i].l);
        if (sh[i].l==0)
          continue;
        add_edge(sh[i].u,sh[i].v,sh[i].l);
        add_edge(sh[i].v,sh[i].u,sh[i].l);
    }
    spfa();
    if (d[t]<l)
    {
        printf("NO\n");
        return 0;
    }
    if (d[t]==l)//注意
    {
        printf("YES\n");
        for (int i=1;i<=m;i++)
        {
            if (sh[i].l==0)
              sh[i].l=inf;
            printf("%d %d %lld\n",sh[i].u,sh[i].v,sh[i].l);
        }
        return 0;
    }
    int wh;
    for (int i=1;i<=m;i++)
    {
        if (sh[i].l==0)
        {
            add_edge(sh[i].u,sh[i].v,1);
            add_edge(sh[i].v,sh[i].u,1);
            spfa();
            if (d[t]>l)
            {
                sh[i].l=1;
                continue;
            }
            sh[i].l=1+l-d[t];
            wh=i;
            break;
        }
    }
    tot=-1;
    memset(first,-1,sizeof(first));
    memset(nxt,-1,sizeof(nxt));
    for (int i=wh+1;i<=m;i++)
    {
        if (sh[i].l==0)
          sh[i].l=inf;
    }
    for (int i=1;i<=m;i++)
    {
        add_edge(sh[i].u,sh[i].v,sh[i].l);
        add_edge(sh[i].v,sh[i].u,sh[i].l);
    }
    spfa();
    if (d[t]!=l)
    {
        printf("NO\n");
        return 0;
    }
    printf("YES\n");
    for (int i=1;i<=m;i++)
      printf("%d %d %lld\n",sh[i].u,sh[i].v,sh[i].l);
}

原文地址:https://www.cnblogs.com/huangchenyan/p/11316995.html

时间: 2024-10-12 00:01:08

CF716D Complete The Graph的相关文章

codeforces 715B:Complete The Graph

Description ZS the Coder has drawn an undirected graph of n vertices numbered from 0 to n - 1 and m edges between them. Each edge of the graph is weighted, each weight is a positive integer. The next day, ZS the Coder realized that some of the weight

Codeforces 715B. Complete The Graph 最短路,Dijkstra,构造

原文链接https://www.cnblogs.com/zhouzhendong/p/CF715B.html 题解 接下来说的“边”都指代“边权未知的边”. 将所有边都设为 L+1,如果dis(S,T) < L ,那么必然无解. 将所有边都设为 1 ,如果 dis(S,T) > L ,那么必然无解. 考虑将任意一条边的权值+1,则 dis(S,T) 会 +0 或者 +1 . 如果将所有边按照某一个顺序不断+1,直到所有边的权值都是L+1了,那么在这个过程中,dis(S,T) 是递增的,而且一定

Codeforces 716D - Complete The Graph(最短路)

题意:给定n个点,m条边,以及起点s,终点t,问你图中是否存在s->t的最短路为L,其中权值为0的可以任意修改. 思路:对给定的边分为2类,权重不为0的直接扔进去建图,权重为0的边先存起来.接着跑一遍堆优化的dij,如果dis[t]小于L,那么无论怎么修改权重0的边都没有办法凑出最短路L: 如果dis[t]=L,那么直接输出:如果dis[t]>L,则将原来事先存起来的边一条一条的加进去,权值设为1.每加一条边就跑一次dij,一旦找到dis[t]<=L,就可以终止并输出. PS:原来堆优化

Codeforces Round #372 (Div. 1) B. Complete The Graph

题目链接:传送门 题目大意:给你一副无向图,边有权值,初始权值>=0,若权值==0,则需要把它变为一个正整数(不超过1e18),现在问你有没有一种方法, 使图中的边权值都变为正整数的时候,从 S 到 T 的最短路恰好等于 L. 若没有输出 "NO",否则输出 "YES",同时输出新图中的所有边权值. 题目思路:二分+最短路(spfa or dijkstra) 闲谈:先%一发杜教,思路来源于看他的代码.然后蒟蒻spfa 982ms,杜教 dijkstra 93m

715B Complete The Graph

传送门 题目大意 给出一个图,一些边带权,另一些边等待你赋权(最小赋为1).请你找到一种赋权方式,使得 s 到 t 的最短路为 L n ≤ 1e3 ,m ≤ 1e4 ,L ≤ 1e9 分析 二分所有边的边权和 使得二分后第p条边权值为k,1~p-1条边权值为inf,剩余边权值为1 对于每种情况跑一次最短路 如果结果小于L则增大点权和否则减少 代码 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 5313 Bipartite Graph 完全二分图 深搜 bitset应用

Bipartite Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 577    Accepted Submission(s): 154 Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he

hdu 5313 Bipartite Graph(dfs染色 或者 并查集)

Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he wants to make the graph become a complete bipartite graph with most edges by adding some extra edges. Soda needs you to tell him the maximum number of edges

HDU5313——DP+vector——Bipartite Graph

Soda has a bipartite graph with n vertices and m undirected edges. Now he wants to make the graph become a complete bipartite graph with most edges by adding some extra edges. Soda needs you to tell him the maximum number of edges he can add. Note: T

HDU 5313 Bipartite Graph(二分图染色+01背包水过)

Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he wants to make the graph become a complete bipartite graph with most edges by adding some extra edges. Soda needs you to tell him the maximum number of edges