1. 程式人生 > 實用技巧 >迪傑斯特拉+拆點 Deliver the Cake - HDU 6805

迪傑斯特拉+拆點 Deliver the Cake - HDU 6805

題意:

t組輸入,給你n個點m條邊。你需要輸出從s點到t點的最短距離,然後是m條邊,每條邊輸入資訊為:

a,b,c 表示從a點到b點的一個無向邊長度為c

每一個點會有一個屬性L、R或M

如果a和b一個為L,另一個為R,那麼a和b之間的距離要增加x,即變為x+c

其他情況權值還是c

題解:

我們可以注意到M型別的點是一個特殊點,無論是L型別還是R型別的點和它相連,它們的距離都不會增加x

那麼我麼可以把M型別的點拆成兩個點,例如a點為M型別的點,那麼我們可以把a點變為L型別的點,a+n點變為R型別的點

這個樣子去構造一個圖,然後如果起點s是一個M型別的點,我們就讓起點s和s+n都和0號點連一條權值為0的無向邊,然後以0為起點跑一邊迪傑斯特拉

否則,就直接以s點為起點跑一邊迪傑斯特拉

程式碼:

#include <stack>
#include <queue>
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const
int INF=0x3f3f3f3f; ll n,m,v[maxn]; char f[maxn]; struct shudui { ll start,val; bool operator < (const shudui y)const { return val>y.val; } } str1,str2; priority_queue<shudui>r; vector<shudui>w[maxn]; void JK(ll st) { memset(v,INF,sizeof(v)); v[st]=0; str1.start
=st; str1.val=0; r.push(str1); while(!r.empty()) { ll x,y; str1=r.top(); r.pop(); x=str1.start; y=str1.val; if(v[x]<y) continue; //說明在這個點再此之後又入隊了 //此次出隊的並不是s到這個點的最短路, //所以在這次更新前點v所連的點已經更過一次了 //所以後面也不會進行鬆弛操作 ll len=w[x].size(); for(ll i=0;i<len;++i) { str2=w[x][i]; if((v[x]+str2.val<v[str2.start])) { v[str2.start]=v[x]+str2.val; str1.start=str2.start; str1.val=v[str2.start]; r.push(str1); } } } } void add_edge(ll a,ll b,ll c) { str2.start=b; str2.val=c; w[a].push_back(str2); str2.start=a; w[b].push_back(str2); } int main() { ll t; scanf("%lld",&t); while(t--) { ll s,t,x; scanf("%lld%lld%lld%lld%lld",&n,&m,&s,&t,&x); for(ll i=0;i<=2*n;++i) w[i].clear(); scanf("%s",f+1); while(m--) { ll a,b,c; scanf("%lld%lld%lld",&a,&b,&c); if(f[a]==f[b]&&(f[a]=='L'||f[b]=='R')) { add_edge(a,b,c); } else if(f[a]!=f[b]&&f[a]!='M'&&f[b]!='M') { add_edge(a,b,c+x); } else if(f[a]=='L'&&f[b]=='M') { add_edge(a,b,c); add_edge(a,b+n,c+x); } else if(f[a]=='M'&&f[b]=='L') { add_edge(a,b,c); add_edge(a+n,b,c+x); } else if(f[a]=='R'&&f[b]=='M') { add_edge(a,b,c+x); add_edge(a,b+n,c); } else if(f[a]=='M'&&f[b]=='R') { add_edge(a+n,b,c); add_edge(a,b,c+x); } else { add_edge(a,b,c); add_edge(a,b+n,c+x); add_edge(a+n,b,c+x); add_edge(a+n,b+n,c); } } ll ans=0; if(f[s]=='M') { add_edge(0,s,0); add_edge(0,s+n,0); JK(0); ans=min(v[t],v[t+n]); } else { JK(s); //printf("%lld %lld \n",v[t],v[t+n]); ans=min(v[t],v[t+n]); } printf("%lld\n",ans); } return 0; }