zoukankan      html  css  js  c++  java
  • CF715B Complete The Graph

    题面

    调出一堆 (sb)​​ 错误的题,例如:"YES" 写成“Yes”将近半下午没了 = =

    给你一张 (n) 个点,(m) 条边的图,每条边有一个正整数权值。有些边的边权未知。你需要给每条权值未知的边确定一个不超过 (10^{18}) 的正整数权值,使得 (S)(T) 的最短路恰好为 (L)

    无解输出 (−1)

    (2 ≤ n ≤ 1000,1 ≤ m ≤ 2000,1 ≤ L ≤ 10^9,S ≠ T)

    solution

    首先把未知的边的权值都赋为最小的正整数 (1), 然后跑一遍最短路,如果最短路的长度大于 (L) 那么最短路肯定不会是 (L)

    如果最短路的恰好等于 (L) 直接输出答案就好了

    对于如果大于 (L)

    一开始是这么想的:跑一遍最短路,然后找出最短路上的可以变化权值的边(一开始为 0 的边)增大权值,直到这条最短路恰好为 L,然后继续跑最短路,判断是否还存在 < L 的最短路,重复这个操作,直到找不到为止,这样到最后肯定存在一条长度为 (L) 的最短路

    发现这样会跑很多次最短路,就没写 (其实是我不会写)

    题解的思路

    跑两次最短路,第一次的记为 (dis[i][0]) 第二次的记为 (dis[i][1])

    先跑完第一次最短路,求出 (need = L - dis[T][0]) 也就是距目标还差多少

    跑第二次最短路的时候,如果到达一个点的最短路可以更新,并且 (dis[u] + e[i].w < dis[v] + need) 就把 (e[i].w) 更新为 (dis[v] + need - dis[u])

    这样走到 (v) 点就相当于最短路加上了 (need) 妙哉 = =

    code

    /*
    work by:Ariel_
    mind: 把未知的边都设为 1,跑一遍最短路,如果最短路大于 L,则一定无解
    如果此时 = L, 此时就是答案
    如果此时小于 L,就调整这条路径上的边,使得它成为 L,然后再跑最短路,重复此操作
    直到最后找不到小于 L 的路径
    判断一条边是否为最短路上的边:两边 dij, 
    */
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #define int long long
    #define rg register
    using namespace std;
    const int M = 1e5 + 5, N = 1e5 + 5;
    const int INF = 0x3f3f3f3f3f3f;
    typedef pair<int, int> PII;
    int read(){
        int x = 0,f = 1; char c = getchar();
        while(c < '0'||c > '9') {if(c == '-') f = -1; c = getchar();}
        while(c >= '0' && c <= '9') {x = x*10 + c - '0'; c = getchar();}
        return x*f;
    }
    int n, m, L, S, T, opt[N], need;
    struct edge{int u, v, nxt, w, fag;}e[M];
    int head[N], E = 1;
    void add_edge(int u, int v, int w, int fag) {
       e[++E] = (edge) {u, v, head[u], w + fag, fag};
       head[u] = E;
    }
    priority_queue<PII, vector<PII>, greater<PII> > q;
    int dis[N][2], vis[N];
    void dij(int k) {
       memset(vis, 0, sizeof vis);
       for (int i = 0; i < n; i++) dis[i][k] = INF;
       dis[S][k] = 0, q.push(make_pair(0, S));
       while(!q.empty()) {
       	  int u = q.top().second; q.pop(); 
    	  if (vis[u]) continue;
    	  vis[u] = 1;
       	  for (int i = head[u]; i; i = e[i].nxt) {
       	  	    int v = e[i].v;
       	  	    if (k == 1) {
       	  	       if (k && e[i].fag && dis[u][1] + e[i].w < dis[v][0] + need)
       	  	       	 e[i].w = e[i ^ 1].w = dis[v][0] + need - dis[u][1];
    			}
       	  	    if (dis[v][k] > dis[u][k] + e[i].w) {
       	  	        dis[v][k] = dis[u][k] + e[i].w;
    			    q.push(make_pair(dis[v][k], v));	
    			 }   
    		}
       }
    }
    signed main(){
       n = read(), m = read(), L = read(), S = read(), T = read();
       for (int i = 1, u, v, w; i <= m; i++) {
       	 u = read(), v = read(), w = read();
       	 add_edge(u, v, w, !w), add_edge(v, u, w, !w);	
       }
       dij(0);
       if (dis[T][0] > L) {
       	  puts("NO"); return 0;
       }
       need = L - dis[T][0];
       dij(1);
       if (dis[T][1] != L) puts("NO");
       else {
       	  puts("YES");
       	  for (int i = 2; i <= E; i += 2)  printf("%lld %lld %lld
    ", e[i].u, e[i].v, e[i].w);
       }
       return 0; 
    }
    
  • 相关阅读:
    浅谈React数据流管理
    Nodejs相关知识
    React其它相关知识点
    React-Native知识点相关
    React状态管理相关
    React设计模式相关
    Node.js调试相关
    Event loop详解(包含Node端)
    JS this详解
    Babel知识点相关
  • 原文地址:https://www.cnblogs.com/Arielzz/p/15044857.html
Copyright © 2011-2022 走看看