zoukankan      html  css  js  c++  java
  • [ BZOJ 3445 ] Roadblock

    (\)

    (Description)


    给出一张(N) 个点(M)条边的无向图,选择一条边使其权值翻倍,求操作后比操作前最短路长度增量最大值。

    • (1le Nle 250)(1le Mle 250000)

    (\)

    (Solution)


    首先这么稠密的图SPFA肯定爆炸

    • 注意到枚举哪条边权值翻倍再跑一遍最短路的做法复杂度是(Theta(M^2logN)),显然会超时。
    • 发现如果不使最短路上的边权翻倍最短路并不会发生变化,所以只需要考虑对原图最短路上的边操作即可。
    • 确定最短路的边可以通过反向枚举,若发现(dis[v]=dis[u]-e[i].w)则找到了上一个点。

    (\)

    (Code)


    #include<cmath>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 255
    #define M 250010
    #define R register
    #define gc getchar
    using namespace std;
    
    bool vis[N];
    int n,m,res,ans,tot=1,hd[N],dis[N];
    
    struct edge{int to,nxt,w;}e[M<<1];
    inline void add(int u,int v,int w){
      e[++tot].w=w; e[tot].to=v;
      e[tot].nxt=hd[u]; hd[u]=tot;
    }
    
    inline int rd(){
      int x=0; bool f=0; char c=gc();
      while(!isdigit(c)){if(c=='-')f=1;c=gc();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
      return f?-x:x;
    }
    
    priority_queue<pair<int,int> > q;
    inline void dij(){
      memset(vis,0,sizeof(vis));
      memset(dis,0x3f,sizeof(dis));
      dis[1]=0; q.push(make_pair(0,1));
      while(!q.empty()){
        int u=q.top().second; q.pop();
        if(vis[u])continue; vis[u]=1;
        for(R int i=hd[u],v;i;i=e[i].nxt)
          if(dis[v=e[i].to]>dis[u]+e[i].w){
            dis[v]=dis[u]+e[i].w;
            q.push(make_pair(-dis[v],v));
          }
      }
    }
    
    vector<int> s;
    inline void find(){
      int u=n;
      while(u!=1){
          for(R int i=hd[u],v;i;i=e[i].nxt)
          if(dis[v=e[i].to]==dis[u]-e[i].w){
            s.push_back(i); u=v; break;
          }
      }
    }
    
    int main(){
      n=rd(); m=rd();
      for(R int i=1,u,v,w;i<=m;++i){
        u=rd(); v=rd(); w=rd();
        add(u,v,w); add(v,u,w);
      }
      dij(); res=dis[n]; find();
      for(R int i=0;i<(int)s.size();++i){
        e[s[i]].w<<=1; e[s[i]^1].w<<=1;
        dij(); ans=max(ans,dis[n]-res);
        e[s[i]].w>>=1; e[s[i]^1].w>>=1;
      }
      printf("%d
    ",ans);
      return 0;
    }
    
  • 相关阅读:
    html 上传图片前预览
    php获取当月天数及当月第一天及最后一天、上月第一天及最后一天实现方法
    php 计算 pdf文件页数
    php 获取半年内每个月的订单数量, 总价, 月份
    php 获取两个数组之间不同的值
    小程序支付功能
    关于nginx的Job for nginx.service failed because the control process exited with error code.错误
    linux 安装 Apollo
    MongoDB待续。。。
    ABP vNext...待续
  • 原文地址:https://www.cnblogs.com/SGCollin/p/9587977.html
Copyright © 2011-2022 走看看