题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6805
题意:张三送蛋糕,使用左手或者右手拿,小镇有三种L、R、M,L只能够左手拿蛋糕通过,R只能右手拿蛋糕进入,M是任意手都可以。n个小镇各自有对应方式,张三每一次换手拿蛋糕都需要消耗x秒。然后有m条路来连接这些城镇(无向),每条路有长度d,每单位长度耗时1秒,现在要求最短时间从s地把蛋糕送到t地
解题思路:
利用拆点的方法,将M点的城镇分别拆分成两个点L和R来进行构图,对于LR的路耗时为d+x,对于RR的路耗时为d,然后利用最短路Dijkstra来处理最短路问题即可。
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
const ll INF=1e18;
const int MAXN=200010;
int n,m,s,t,x;
char str[MAXN];
struct qnode{
int v;
ll c;
qnode(int _v=0,ll _c=0):v(_v),c(_c){}
bool operator <(const qnode &r)const{
return c>r.c;
}
};
struct Edge{
int v;
ll cost;
Edge(int _v=0,ll _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E[MAXN];
bool vis[MAXN];
ll dist[MAXN];
//int path[MAXN];
//点的编号从 1 开始
void Dijkstra(int start){
memset(vis,false,sizeof(vis));
for(int i=1;i<=2*n;i++)dist[i]=INF;
priority_queue<qnode>que;
while(!que.empty())que.pop();
dist[start]=0;
que.push(qnode(start,0));
qnode tmp;
while(!que.empty()){
tmp=que.top();
que.pop();
int u=tmp.v;
if(vis[u])continue;
vis[u]=true;
for(int i=0;i<E[u].size();i++){
int v=E[tmp.v][i].v;
ll cost=E[u][i].cost;
/*if(str[u]!=str[v])
cost+=x;*/
if(!vis[v]&&dist[v]>dist[u]+cost){
dist[v]=dist[u]+cost;
//path[v]=u;
que.push(qnode(v,dist[v]));
}
}
}
}
void addedge(int u,int v,ll w){
E[u].push_back(Edge(v,w));
}
int main(){
//freopen("D.in","r",stdin);
int tt;
scanf("%d",&tt);
while(tt--){
scanf("%d%d%d%d%d",&n,&m,&s,&t,&x);
scanf("%s",str+1);
for(int i=1;i<=2*n;i++)
E[i].clear();
for(int i=1;i<=m;i++){
int a,b;
ll w;
scanf("%d%d%lld",&a,&b,&w);
if((str[a]=='L'&&str[b]=='R')||(str[a]=='R'&&str[b]=='L')){
addedge(a,b,w+x);
addedge(b,a,w+x);
}
else if((str[a]=='L'&&str[b]=='L')||(str[a]=='R'&&str[b]=='R')){
addedge(a,b,w);
addedge(b,a,w);
}
else if(str[a]=='M'){
if(str[b]=='L'){
addedge(a,b,w); //LL
addedge(b,a,w);
addedge(a+n,b,w+x); //RL
addedge(b,a+n,w+x);
}
else if(str[b]=='R'){
addedge(a+n,b,w); //RR
addedge(b,a+n,w);
addedge(a,b,w+x); //LR
addedge(b,a,w+x);
}
else{
addedge(a,b,w); //LL
addedge(b,a,w);
addedge(a+n,b,w+x); //RL
addedge(b,a+n,w+x);
addedge(a,b+n,w+x); //LR
addedge(b+n,a,w+x);
addedge(a+n,b+n,w); //RR
addedge(b+n,a+n,w);
}
}
else if(str[b]=='M'){
if(str[a]=='L'){
addedge(a,b,w); //LL
addedge(b,a,w);
addedge(a,b+n,w+x); //LR
addedge(b+n,a,w+x);
}
else if(str[a]=='R'){
addedge(a,b+n,w); //RR
addedge(b+n,a,w);
addedge(a,b,w+x); //RL
addedge(b,a,w+x);
}
}
}
//考虑如果起点或终点为M,被拆开的情况
Dijkstra(s);
ll ans=INF;
ans=min(dist[t],ans);
if(str[t]=='M')
ans=min(dist[t+n],ans);
if(str[s]=='M'){
Dijkstra(s+n);
ans=min(dist[t],ans);
if(str[t]=='M')
ans=min(dist[t+n],ans);
}
cout<<ans<<endl;
}
return 0;
}