BZOJ 4289: PA2012 Tax 最短路 建图

来源:互联网 发布:ubuntu win7 系统时间 编辑:程序博客网 时间:2024/05/29 18:15

4289: PA2012 Tax

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 677  Solved: 213
[Submit][Status][Discuss]

Description

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

Sample Input

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

Sample Output

12

考虑边化点 两个有公共点的边连一条权值为max的边 之后跑最短路

但是显然 菊花就能卡成空间n^2


这时就需要高超的建图技巧

每条边拆成两条有向边 中间连原本权值

每个点的出边按权值从小到大排序 

小的向第一个比他大的连两边差的权值

打到向第一个比他小的连0

建S向1的出边连其权值的边

建T由n的入边向其连权值的边


#include<cmath>#include<ctime>#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#include<iomanip>#include<vector>#include<string>#include<bitset>#include<queue>#include<set>#include<map>using namespace std;typedef double db;typedef long long ll;inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}return x*f;}void print(int x){if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}const int N=1000100;int last[N],ecnt;struct EDGE{int to,nt,val;}e[N<<1];inline void add(int u,int v,int val){e[++ecnt]=(EDGE){v,last[u],val};last[u]=ecnt;}bool operator <(const EDGE &x,const EDGE &y){return x.val<y.val;}int n,m;ll dis[N];struct point{ll dis;int pos;friend bool operator <(const point &x,const point &y){return x.dis>y.dis;}};bool used[N];priority_queue<point>q;void dijkstra(){memset(dis,0X3f,sizeof(dis));register int i,u;dis[1]=0;q.push((point){0,1});while(!q.empty()){u=q.top().pos;q.pop();if(used[u]) continue;used[u]=1;for(i=last[u];i;i=e[i].nt)if(dis[e[i].to]>dis[u]+e[i].val){dis[e[i].to]=dis[u]+e[i].val;if(!used[e[i].to])q.push((point){dis[e[i].to],e[i].to});}}}vector<EDGE> vec[N];int main(){n=read();m=read();register int i,j,u,v,val;for(i=1;i<=m;++i){u=read();v=read();val=read();vec[u].push_back((EDGE){v,i<<1,val});vec[v].push_back((EDGE){u,i<<1|1,val});add(i<<1,i<<1|1,val);add(i<<1|1,i<<1,val);}for(i=1;i<=n;++i){sort(vec[i].begin(),vec[i].end());if(vec[i].size()>1)for(j=1;j<vec[i].size();++j)add(vec[i][j-1].nt,vec[i][j].nt,vec[i][j].val-vec[i][j-1].val),add(vec[i][j].nt,vec[i][j-1].nt,0);}for(i=0;i<vec[1].size();++i)add(1,vec[1][i].nt,vec[1][i].val);for(i=1;i<=n;++i)for(j=0;j<vec[i].size();++j)if(vec[i][j].to==n)add(vec[i][j].nt,(m<<1)+2,vec[i][j].val);dijkstra();cout<<dis[(m<<1)+2]<<endl;return 0;}/*4 51 2 51 3 22 3 12 4 43 4 812*/