CF716D Complete The Graph

Posted huangchenyan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);

 

以上是关于CF716D Complete The Graph的主要内容,如果未能解决你的问题,请参考以下文章

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

codeforces 715B:Complete The Graph

715B Complete The Graph

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

[CF715E] Complete the Permutations(dp+组合计数)

CF724G. Xor-matic Number of the Graph