BZOJ.4289.PA2012 Tax(思路 Dijkstra)
阿新 • • 發佈:2018-02-24
排序 cnblogs std build get amp void next reg ,\((j,j',v2-v1)\)
最後起點處的代價沒有被計算,在起點的每條出邊加上一個點即可
復雜度O(mlogm)
很像的邊表邊很容易寫錯。。
不會寫代碼。。
沒有邊權範圍要longlong
題目鏈接
\(Description\)
給出一個N個點M條邊的無向圖,經過一個點的代價是進入和離開這個點的兩條邊的邊權的較大值,求從起點1到點N的最小代價。起點的代價是離開起點的邊的邊權,終點的代價是進入終點的邊的邊權。
\(Solution\)
最直接的方法是把每條邊作為一個點,對於連接同一個點的兩條邊連一條新邊,最後把連接1和n的點分別連S、T,跑最短路
但這樣邊數是O(m^2)的
對於路徑上相鄰兩條邊\((i,j,v1)\)和\((j,k,v2)\),v1<v2,考慮如何構圖把v1比v2小的部分補上
那麽對於點j拆點,每個點對應一條出邊或入邊,按邊權排序,設相鄰兩點對應權值為v1,v2(v1<v2),那麽建邊\((j',j,0)\)
最後起點處的代價沒有被計算,在起點的每條出邊加上一個點即可
復雜度O(mlogm)
很像的邊表邊很容易寫錯。。
不會寫代碼。。
沒有邊權範圍要longlong
//35772kb 1892ms
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
//#define gc() getchar()
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define pr std::pair<LL,int>
#define mp std::make_pair
typedef long long LL;
const int N=4e5+5,M=4e5+5,MAXIN=3e6;//N:兩倍邊數
const LL INF=1ll<<60;
int src,des,n,m,Enum,H[N],nxt[M<<2],to[M<<2],val[M<<2],tmp[M];//邊數一直錯。。mdzz 開始一共4e5條邊
int num,h[N>>1],tto[M],tnxt[M],tval[M];
LL dis[N];
bool vis[N];
char IN[MAXIN],*SS=IN,*TT=IN;
std::priority_queue<pr> q;
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
inline bool cmp(int i,int j) {return tval[i]<tval[j];}
inline void Add(int u,int v,int w){
tto[++num]=v, tnxt[num]=h[u], tval[num]=w, h[u]=num;
}
inline void AddEdge(int u,int v,int w){
to[++Enum]=v, nxt[Enum]=H[u], val[Enum]=w, H[u]=Enum;
}
void Build()
{
src=1, des=(m+1)<<1;
for(int i=1; i<=n; ++i)
{
int cnt=0;
for(int j=h[i]; j; j=tnxt[j])
tmp[++cnt]=j;//存編號就行了
std::sort(tmp+1,tmp+1+cnt,cmp);
for(int now,next,j=1; j<=cnt; ++j)//~
{
now=tmp[j], next=tmp[j+1];//直接拿邊號來建就可以了 也是建的雙向邊
if(i==1) AddEdge(src,now,tval[now]);//把連向src的邊拆出一個點來
if(tto[now]==n) AddEdge(now,des,tval[now]);
AddEdge(now^1,now,tval[now]);//只建一條邊 還有另一個點的邊
if(j<cnt) AddEdge(now,next,tval[next]-tval[now]), AddEdge(next,now,0);
}
// if(cnt) AddEdge(tmp[cnt]^1,tmp[cnt],tval[tmp[cnt]]);//WA!沒有上面兩個條件特判!
}
}
LL Dijkstra()
{
for(int i=src+1; i<=des; ++i) dis[i]=INF;
dis[src]=0, q.push(mp(0,src));
while(!q.empty())
{
int x=q.top().second; q.pop();
if(vis[x]) continue;
if(x==des) return dis[x];
vis[x]=1;
for(int v,i=H[x]; i; i=nxt[i])
if(!vis[v=to[i]] && dis[v]>dis[x]+val[i])
dis[v]=dis[x]+val[i], q.push(mp(-dis[v],v));
}
return dis[des];
}
int main()
{
n=read(),m=read();
num=1;
for(int u,v,w,i=1; i<=m; ++i)
u=read(),v=read(),w=read(),Add(u,v,w),Add(v,u,w);
Build();
printf("%lld",Dijkstra());
return 0;
}
BZOJ.4289.PA2012 Tax(思路 Dijkstra)