bzoj 4289: PA2012 Tax(最短路+建图)

4289: PA2012 Tax

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 182   Solved: 75
[ Submit][ Status][ Discuss]

Description

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

Input

Output

Sample Input

4 5
1 2 5
1 3 2
2 3 1
2 4 4
3 4 8

Sample Output

12

HINT


Source

[ Submit][ Status][ Discuss]

#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<algorithm>  
#include<vector>  
#include<queue>  
#define N 2000000  
#define M 400003
#define LL long long  
#define inf 1000000000  
#define pa pair<long long,int>   
using namespace std;  
int n,m,tot,tot1,s,t;  
int head[M],nxt[M],v1[M],point[N],next[N],v[N],num[N];  
LL len[N],c[N],dis[N];  
struct data  
{  
    int l,r; LL x;  
}a[M];  
void add(int x,int y,LL z)  
{  
    tot1++; nxt[tot1]=head[x]; head[x]=tot1; v1[tot1]=y; len[tot1]=z;   
    tot1++; nxt[tot1]=head[y]; head[y]=tot1; v1[tot1]=y; len[tot1]=z;   
}  
void build(int x,int y,LL z)  
{  
    tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;  
}  
void dijkstra(int s,int t)    
{    
    priority_queue<pa,vector<pa>,greater<pa> > q;    
    for (int i=0;i<=t;i++)    
     dis[i]=inf*(LL)(n+1);    
    dis[s]=0;  q.push(make_pair(dis[s],s));    
    while(!q.empty())    
    {    
        int now=q.top().second; q.pop();     
        for (int i=point[now];i!=-1;i=next[i])    
         if (dis[now]+c[i]<dis[v[i]])    
         {    
            dis[v[i]]=dis[now]+c[i];    
            q.push(make_pair(dis[v[i]],v[i]));    
         }    
    }    
}    
int cmp(data a,data b)  
{  
    return a.x<b.x;  
}  
int main()  
{  
    scanf("%d%d",&n,&m);  
    tot1=-1;  
    memset(head,-1,sizeof(head));  
    memset(nxt,-1,sizeof(nxt));  
    tot=-1;  
    memset(point,-1,sizeof(point));  
    memset(next,-1,sizeof(next));  
    for (int i=1;i<=m;i++)  
    {  
        int x,y; LL z; scanf("%d%d%lld\n",&x,&y,&z);  
        add(x,y,z);  
    }  
    for (int i=1;i<=n;i++)  
    {  
        int cnt=0;  
        for (int j=head[i];j!=-1;j=nxt[j])  
         {  
            ++cnt;  
            a[cnt].l=j^1;  
            a[cnt].r=j;  
            a[cnt].x=len[j];  
         }  
        sort(a+1,a+cnt+1,cmp);   
        for (int j=1;j<=cnt;j++)  
        {  
            build(a[j].l,a[j].r,a[j].x);  
            if (j!=1)  build(a[j].r,a[j-1].r,0);  
            if (j!=cnt) build(a[j].r,a[j+1].r,abs(a[j+1].x-a[j].x));  
        }  
    }  
    s=tot1+1; t=s+1;  
    for (int i=head[1];i!=-1;i=nxt[i])  
     build(s,i,len[i]);  
    for (int i=head[n];i!=-1;i=nxt[i])  
     build(i,t,0);  
    dijkstra(s,t);  
    printf("%lld\n",dis[t]);  
}  




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值