HDU-6805
n个点,m条路的无向图,给出每条路的耗时w,求张三从起点面包店s到家终点t的最短路,另外张三手里(左手或者右手)提着东西,每个点有一个值规定在该点张三需要用那只手提东西;
L表示用左手提;
R表示用右手提;
M表示用左右手都可以;
换手时需要额外花时间x;
把M的点拆分成两个点L和R,根据每条边连接的点将换手的权值加入到边权中;
例如:点a到点b有条边,权值val,a为M,b为M
我们统一将拆分出来的R的点放置在点的索引+n的位置,即点a+n为R的点,而a为L的点,同理b也如此拆分;
接下来建边:
1、如果边连接的两点都为L或者R就直接建立权值为w的边;
2、如果边连接的两点,一个为L,一个为R,就建立一条w+x的边;
最后对建好的图跑dij,注意终点和起点有可能是M,那么就有两个起点s和s+n和两个终点t和t+n,不同起点跑两遍dij,比较最小值,每次dij要比较两个终点的最小值;
/*
* @author: arc
* @date: 2020-08-01 00:39:24
*/
const int maxn = 4e6+5;
struct node{
int to;
int next;
ll w;
bool operator<(const node&a) const{
return a.w < w;
}
}edge[maxn],Now,Next;
int head[maxn], cnt;
bool vis[maxn];
ll dis[maxn];
int n, s, t, m;
ll x;
char hand[maxn];
void init(){
MS1(head);
cnt = 0;
}
void add(int u, int v, int w){
edge[++cnt].to = v;
edge[cnt].next = head[u];
edge[cnt].w = w;
head[u] = cnt;
}
ll dijkstra(int s){
MS0(vis);
for (int i = 1; i <= 2 * n+1; i++){
dis[i] = 1LL<<61LL;
}
Now.to = s;
dis[s] = 0;
priority_queue<node>pq;
pq.push(Now);
while(!pq.empty()){
Now = pq.top();
pq.pop();
int now = Now.to;
if(vis[now]) continue;
vis[now] = 1;
for(int i=head[now]; i!=-1; i=edge[i].next){
int u = edge[i].to;
if(!vis[u] && dis[u] > dis[now] + edge[i].w){
dis[u] = dis[now] + edge[i].w;
Next.to = u;
Next.w = dis[u];
pq.push(Next);
}
}
}
return min(dis[t], dis[t + n]);
}
int main(){
int cas;
scanf("%d", &cas);
while(cas--){
int m;
init();
scanf("%d%d%d%d%lld", &n, &m, &s, &t, &x);
hand[0] = '#';
scanf("%s", hand+1);
for (int i = 0; i < m; i++){
int from, to;
ll val;
scanf("%d%d%lld", &from, &to, &val);
if((hand[from] == 'L' && hand[to] == 'R') || (hand[from] == 'R' && hand[to] == 'L')){
add(from, to, val + x);
add(to, from, val + x);
} else if((hand[from] == 'L' && hand[to] == 'L') || (hand[from] == 'R' && hand[to] == 'R')){
add(from, to, val);
add(to, from, val);
} else if(hand[from] == 'M' && hand[to] == 'L'){
add(from, to, val);
add(to, from, val);
add(from + n, to, val + x);
add(to, from + n, val + x);
} else if(hand[from] == 'L' && hand[to] == 'M'){
add(from, to, val);
add(to, from, val);
add(from, to + n, val + x);
add(to + n, from, val + x);
} else if(hand[from] == 'M' && hand[to] == 'R'){
add(from, to, val + x);
add(to, from, val + x);
add(from + n, to, val);
add(to, from + n, val);
} else if(hand[from] == 'R' && hand[to] == 'M'){
add(from, to, val + x);
add(to, from, val + x);
add(from, to + n, val);
add(to + n, from, val);
} else if(hand[from] == 'M' && hand[to] == 'M'){
add(from, to, val);
add(to, from, val);
add(from + n, to + n, val);
add(to + n, from + n, val);
add(from, to + n, val + x);
add(to + n, from, val + x);
add(from + n, to, val + x);
add(to, from + n, val + x);
}
}
printf("%lld\n", min(dijkstra(s), dijkstra(s + n)));
}
}
/*
12
3 3 1 3 100
MRM
1 2 10
2 3 10
1 3 100
*/