1. 程式人生 > >【Bzoj4289】PA2012 Tax(Dijkstra+技巧建圖)

【Bzoj4289】PA2012 Tax(Dijkstra+技巧建圖)

down getc cmp priority 無向圖 mes post 起點 con

Description

給出一個N個點M條邊的無向圖,經過一個點的代價是進入和離開這個點的兩條邊的邊權的較大值,求從起點1到點N的最小代價。起點的代價是離開起點的邊的邊權,終點的代價是進入終點的邊的邊權

N<=100000

M<=200000

Solution

這題關鍵在於化邊為點,把無向邊拆成2條有向邊

考慮最直白的一種建圖方法,對於每一個點u,它的每一條入邊向所有出邊連邊

但這樣邊數太多了,最壞是\(M^2\)條邊,不可行

考慮用差值來建圖,每條出邊向第一條比它大的出邊連一條權值為權差值的邊,並且反向連一條權值為0的邊

然後每條入邊向對應的出邊連一條為自身權值的邊

設一個超級源點S和匯點T,S向1的所以出邊連邊,n的所以出邊向T連邊

這樣邊數是m級別的,然後跑最短路即可,

這題邊數較多,我用spfa過不了,用Dijkstra堆優化可以過

Code

#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#define ll long long
#define Pa pair<ll,int>
using namespace std;

struct info{int to,nex,w;}e[400010],ne[2000010];
int n,m,tot=1,head[400010],nhead[400010
],S,T; ll dis[400010]; priority_queue<Pa,vector<Pa>,greater<Pa> > q; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return
x*f; } inline void Link(int u,int v,int w){ e[++tot].to=v;e[tot].w=w;e[tot].nex=head[u];head[u]=tot; } inline void nLink(int u,int v,int w){ ne[++tot].to=v;ne[tot].w=w;ne[tot].nex=nhead[u];nhead[u]=tot; } bool cmp(int a,int b){return e[a].w<e[b].w;} int tmp[400010],tp; void Build(){ tot=1; S=1,T=m*2+2; for(int i=1;i<=n;++i){ tp=0; for(int j=head[i];j;j=e[j].nex) tmp[++tp]=j; sort(tmp+1,tmp+tp+1,cmp); for(int j=1;j<=tp;++j){ int u=tmp[j],nex=tmp[j+1]; if(e[u].to==n) nLink(u,T,e[u].w); if(i==1) nLink(S,u,e[u].w); nLink(u^1,u,e[u].w); if(j<tp) nLink(u,nex,e[nex].w-e[u].w),nLink(nex,u,0); } } } void Dijkstra(){ for(int i=S;i<=T;++i)dis[i]=1ll<<60; q.push(make_pair(0,S)); dis[S]=0; while(!q.empty()){ int u=q.top().second; ll Dis=q.top().first; q.pop(); if(Dis>dis[u]) continue; for(int i=nhead[u];i;i=ne[i].nex){ int v=ne[i].to; if(dis[v]>dis[u]+ne[i].w){ dis[v]=dis[u]+ne[i].w; q.push(make_pair(dis[v],v)); } } } } int main(){ n=read(),m=read(); for(int i=1;i<=m;++i){ int u=read(),v=read(),w=read(); Link(u,v,w); Link(v,u,w); } Build(); Dijkstra(); printf("%lld\n",dis[T]); return 0; }

【Bzoj4289】PA2012 Tax(Dijkstra+技巧建圖)