zoukankan      html  css  js  c++  java
  • BZOJ 4289: PA2012 Tax Dijkstra + 查分

    Description

    给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价。起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边权
    N<=100000
    M<=200000
     

    Input

    Output

    那个取最大值的操作十分烦人,考虑如何将这个判断去掉.
    可以用查分的方式:如果进来的边是小的,那么从大的边出去就要补齐差值.
    补齐差值就直接连一条差值为 $d$ 的边即可.
    然后跑一个 $Dijkstra$ 即可.

    #include <cstdio>  
    #include <queue> 
    #include <algorithm>
    #include <cstring>
    #include <map>         
    #define N 400003 
    #define inf 10000000000000 
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;               
    namespace IO
    {
        char *p1, *p2, buf[100000];
     
        #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
     
        int rd() {
            int x = 0, f = 1;
            char c = nc();
            while (c < 48) {
                if (c == '-')
                    f = -1;
                c = nc();
            }
            while (c > 47) {
                x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
            }
            return x * f;
        }
    };           
    struct Edge 
    { 
        int to,dis;      
        Edge(int to=0,int dis=0):to(to),dis(dis){} 
    }; 
    vector<Edge>G[N];       
    bool cmp(Edge a,Edge b) 
    {
        return a.dis<b.dis;    
    }   
    map<int,int>id[N]; 
    int n,m,cnt,edges,s,t;  
    int hd[N*6],nex[N*6],to[N*6],done[N*6];      
    ll d[N*6],val[N*6]; 
    inline void addedge(int u,int v,int c) 
    {    
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=1ll*c;   
    }    
    struct Node 
    {
        ll dis;  
        int u;
        Node(ll dis=0,int u=0):dis(dis),u(u){}   
        bool operator<(Node b) const 
        {
            return dis>b.dis;        
        }
    };    
    priority_queue<Node>q; 
    inline void Dijkstra() 
    {
        int i; 
        for(i=0;i<=t;++i) d[i]=inf, done[i]=0;    
        d[s]=0, q.push(Node(0,s));                     
        while(!q.empty()) 
        {
            Node e=q.top();q.pop();   
            if(done[e.u]) continue;   
            done[e.u]=1;                 
            int u=e.u; 
            for(i=hd[u];i;i=nex[i]) 
            {
                int v=to[i]; 
                if(d[u]+val[i]<d[v]) 
                {
                    d[v]=d[u]+val[i];   
                    q.push(Node(d[v],v));   
                }
            }
        }    
    }
    int main() 
    {
        int i,j; 
        // setIO("input");    
        n=IO::rd(),m=IO::rd(); 
        for(i=1;i<=m;++i) 
        {
            int a=IO::rd(),b=IO::rd(),c=IO::rd(); 
            G[a].push_back(Edge(b,c)), G[b].push_back(Edge(a,c));
        } 
        for(i=1;i<=n;++i) 
        {
            sort(G[i].begin(),G[i].end(),cmp); 
            if(G[i].empty()) continue;  
            id[i][G[i][0].dis]=++cnt;     
            for(j=1;j<(int)G[i].size();++j) if(G[i][j].dis!=G[i][j-1].dis) id[i][G[i][j].dis]=++cnt; 
        }  
        for(i=1;i<=n;++i) 
        {   
            int k,lst=0,pre=0; 
            for(k=0;k<(int)G[i].size();k=j+1) 
            {
                j=k;   
                int cur=id[i][G[i][j].dis];        
                while(j<(int)G[i].size()-1&&G[i][j+1].dis==G[i][j].dis) ++j;      
                if(lst) addedge(cur,lst,0), addedge(lst,cur,G[i][k].dis-pre);    
                for(int o=k;o<=j;++o) addedge(cur, id[G[i][o].to][G[i][o].dis], G[i][o].dis);         
                lst=cur, pre=G[i][k].dis;    
            }
        }
        s=0, t=cnt+2;   
        for(i=0;i<G[1].size();++i)  if(i==0||G[1][i].dis!=G[1][i-1].dis) addedge(s,id[1][G[1][i].dis],G[1][i].dis);   
        for(i=0;i<G[n].size();++i)  if(i==0||G[n][i].dis!=G[n][i-1].dis) addedge(id[n][G[n][i].dis],t,0);   
        Dijkstra(), printf("%lld
    ",d[t]);   
        return 0; 
    }
    

      

  • 相关阅读:
    vue 点击出现下拉菜单,点击下拉菜单以外都要关闭菜单
    关于SET ANSI_PADDING的用法
    VUE中的/deep/用法
    VUE中的/deep/用法
    数字与字符串系列教材 (十)- 自己开发一个Java StringBuffer
    数字与字符串系列教材 (九)- Java StringBuffer常见方法
    数字与字符串系列教材 (八)- Java 比较字符串详解
    数字与字符串系列教材 (七)- Java常见字符串方法
    数字与字符串系列教材 (六)- Java中的字符串String详解
    数字与字符串系列教材 (六)- Java中的字符串String详解
  • 原文地址:https://www.cnblogs.com/guangheli/p/11388494.html
Copyright © 2011-2022 走看看