首先咱們考慮把無向圖變成有向圖,而後化邊爲點,新圖中兩點之間距離爲邊權的max,而後新建源點S向1的出邊化成的點連邊,邊權爲出邊邊權,新建匯點T,n的入邊化成的點向T連邊,邊權爲入邊邊權。而後S到T的最短路就是答案。這樣最壞是
的邊。
考慮優化建圖:由於
,因此咱們能夠先支付a的價格,再考慮補差價。
考慮一個點i的全部出邊,按權值從小到大排序,而後第j小的邊向第j+1小的邊連邊,權值爲邊權差,第j+1小的邊向第j小的邊連邊,邊權爲0,由於每條邊都是咱們用原來的無向邊拆的,因此對於一個點i的入邊j,必定有一條點i的出邊j’存在,咱們建邊(j->j’)權值爲邊權。這樣仍是知足題意的,而且邊數優化到了
。html
#include <bits/stdc++.h> using namespace std; #define ll long long #define inf 0x3f3f3f3f #define N 200010 #define pa pair<ll,int> int n,m,tot=0,h[N<<1],num=0,s=1,t; ll dis[N<<1]; bool f[N<<1]; vector<int>a[N>>1];// out edge id struct edge{ int fr,to,val; }e[N<<1]; struct Edge{ int to,nxt,val; }data[N*6]; inline void add(int x,int y,int val){ data[++num].to=y;data[num].nxt=h[x];h[x]=num;data[num].val=val; } inline void add1(int id,int x,int y,int val){ e[id].fr=x;e[id].to=y;e[id].val=val;a[x].push_back(id); if(x==1) add(s,id,val);if(y==n) add(id,t,val); } inline bool cmp(int x,int y){return e[x].val<e[y].val;} inline void Dij(){ priority_queue<pa,vector<pa>,greater<pa> >q; memset(dis,inf,sizeof(dis));memset(f,0,sizeof(f)); q.push(make_pair(0,s));dis[s]=0; while(!q.empty()){ int x=q.top().second;q.pop();if(f[x]) continue;f[x]=1; for(int i=h[x];i;i=data[i].nxt){ int y=data[i].to; if(dis[x]+data[i].val<dis[y]){ dis[y]=dis[x]+data[i].val; q.push(make_pair(dis[y],y)); } } } } int main(){ // freopen("a.in","r",stdin); scanf("%d%d",&n,&m);t=m+1<<1; for(int i=1;i<=m;++i){ int x,y,z;scanf("%d%d%d",&x,&y,&z); add1(i<<1,x,y,z);add1(i<<1|1,y,x,z); add(i<<1,i<<1|1,z);add(i<<1|1,i<<1,z); } for(int i=1;i<=n;++i){ sort(a[i].begin(),a[i].end(),cmp); for(int j=0;j<a[i].size();++j){ if(j) add(a[i][j],a[i][j-1],0); if(j+1<a[i].size()) add(a[i][j],a[i][j+1],e[a[i][j+1]].val-e[a[i][j]].val); } } Dij(); printf("%lld\n",dis[t]); return 0; }