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\n",d[t]);   
    return 0; 
}

  

posted @ 2019-08-21 14:17  EM-LGH  阅读(120)  评论(0编辑  收藏  举报