Deliver the Cake
题意
给出nm的无向图,从st走向end,图中点分为左中右三种要求,左的点要求经过时状态必须为左,右同理,中则无特殊要求需求,出发选择一种状态,状态切换需要额外花费x。问最小花费。
思路
易知进入中后,选择的左或右状态具有后效性。直接把中需求的点拆为左右两个点即可。
代码
比赛时候写的太乱了=-=代码以后改。
#include<bits/stdc++.h>
#define ll long long
#define INF 1e18
using namespace std;
const int maxn=2e6+10;
ll xx;
char zh[maxn];
struct Edge
{
ll from,to,dist;
Edge(ll f,ll t,ll d):from(f),to(t),dist(d){}
};
struct HeapNode
{
ll d,u;
HeapNode(ll d,ll u):d(d),u(u){}
bool operator <(const HeapNode&rhs)const
{
return d>rhs.d;
}
};
struct Dijkstra{
int n,m;
vector<Edge> edges;
vector<int> G[maxn];
bool done[maxn];
ll d[maxn];
void init(int n)
{
this->n=n;
for(int i=0;i<n+5;i++) G[i].clear();
edges.clear();
}
void AddEdge(ll from,ll to,ll dist)
{
edges.push_back(Edge(from,to,dist));
m = edges.size();
G[from].push_back(m-1);
}
ll dijkstra(int st,int ed){
priority_queue<HeapNode> Q;
for(int i=0;i<n*2+1000;i++) d[i]=INF;
d[st]=d[st+n]=0;
Q.push(HeapNode(d[st],st));//st也mid
if(zh[st]=='M')Q.push(HeapNode(d[st+n],st+n));
memset(done,0,sizeof(done));
while(!Q.empty()){
HeapNode x=Q.top(); Q.pop();
int u=x.u;
if(done[u]) continue;
done[u]=true;
char ty;
if(u>n){
ty='R';
u=u-n;
}
else if(zh[u]=='M')ty='L';
else ty='0';
for(int i=0;i<G[u].size();i++){
Edge &e=edges[G[u][i]];
if(ty=='0'){
if(zh[e.to]=='M'){
int v1=e.to,v2=e.to+n;
ll l1=d[u]+e.dist,l2=d[u]+e.dist;
if(zh[u]=='L')l2+=xx;
else l1+=xx;
if(d[v1]>l1){
d[v1]=l1;
Q.push(HeapNode(d[v1],v1));
}
if(d[v2]>l2){
d[v2]=l2;
Q.push(HeapNode(d[v2],v2));
}
}
else{
int v1=e.to;
ll l1=d[u]+e.dist;
if(zh[v1]!=zh[u])l1+=xx;
if(d[v1]>l1){
d[v1]=l1;
Q.push(HeapNode(d[v1],v1));
}
}
}
else{
if(zh[e.to]=='M'){
int v1=e.to;
if(ty=='R')v1+=n;
ll l1=d[u]+e.dist;
if(ty=='R')l1=d[u+n]+e.dist;
if(d[v1]>l1){
d[v1]=l1;
Q.push(HeapNode(d[v1],v1));
}
}
else{
int v1=e.to;
ll l1=d[u]+e.dist;
if(ty=='R')l1=d[u+n]+e.dist;
if(zh[v1]!=ty)l1+=xx;
if(d[v1]>l1){
d[v1]=l1;
Q.push(HeapNode(d[v1],v1));
}
}
}
}
}
return min(d[ed-1],d[ed-1+n]);
}
}DJ,AJ;
void Slove(){
int n,m,st,ed;
scanf("%d%d%d%d%lld",&n,&m,&st,&ed,&xx);
DJ.init(n*2+5);
scanf("%s",zh);
for(int i=0;i<m;i++){
int u,v;
ll d;
scanf("%d%d%lld",&u,&v,&d);
u--,v--;
DJ.AddEdge(u,v,d);
DJ.AddEdge(v,u,d);
}
ll ans=DJ.dijkstra(ed-1,st);
printf("%lld\n",ans);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
Slove();
}
return 0;
}