hdu6805 Deliver The Cake // Dijkstra&拆点
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6805
题目大意 :给定n个点,m条边的图;对于每一个点,其具有L/R/M的属性,表示通过该点时必须选择 左/右/皆可 手持蛋糕;对于每一条边,有长度为x的权值,可直接视作经过某一条边消耗的时间;而在行进过程中,可以通过消耗一定时间交替左右手。请你求出由起点抵达终点可以消耗的最短时间。
主要思路:
1. Vector存图;
2. 通过拆分所有属性为M的点,将原图扩展;
3. Dijkstra跑一遍扩展后的图(优先队列)
4. 得出结果
ps:算法过程有待进一步优化。然鹅别的题还没搞完...溜溜球
咕~
*转载请注明出处 谢谢
#include<iostream>
#include<algorithm>
#include<queue>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long
#define INF 1e12
using namespace std;
const int maxn = 1e5+10;
const int maxm = 2e5+10;
typedef pair<int, ll> PII;
int n, m, s, t;
ll x;
vector<PII> v[maxm];
char type[maxn];
ll dis[maxm];
bool vis[maxm];
struct node
{
int id;
ll val;
//node(int a, ll b){id = a, val = b;}
bool operator <(const node &t)const{
return val > t.val;
}//
} ;
inline void Add_Edge(int a, int b, int x)
{
v[a].push_back({b, x});
v[b].push_back({a, x});
}
ll dijkstra()
{
for(int i = 0 ; i <= n * 2 + 1 ; i++){
dis[i] = INF;
vis[i] = false;
}
priority_queue<node> q;
if(type[s] == 'M'){
dis[0] = 0;
q.push({0, 0});// {id, val}
}else{
dis[s] = 0;
q.push({s, 0});
}
while(!q.empty()){
node N = q.top();
q.pop();
int ID = N.id;
if(vis[ID] == true) continue;
vis[ID] = true;
int sz = (int)v[ID].size();
for(int i = 0 ; i < sz ; i++){
int now = v[ID][i].first;
ll nowval = v[ID][i].second;
if(!vis[now] && dis[ID] + nowval < dis[now]){
dis[now] = dis[ID] + nowval;
q.push({now, dis[now]});
}
}
}
if(type[t] == 'M'){
return dis[n << 1 | 1];
}else{
return dis[t];
}
}
int main(){
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d%lld",&n,&m,&s,&t,&x);
//s--; t--;
scanf("%s",type+1);
int nx = n << 1 | 1;//
for(int i = 0 ; i <= nx ; i++){
v[i].clear();
}
if(type[s] == 'M'){
Add_Edge(0 ,s ,0);Add_Edge(s ,0 ,0);
Add_Edge(0 ,s + n ,0);Add_Edge(s + n ,0 ,0);
}
if(type[t] == 'M'){
Add_Edge(nx ,t ,0);Add_Edge(t ,nx ,0);
Add_Edge(nx ,t + n ,0);Add_Edge(t + n ,nx ,0);
}
for(int i = 0 ; i < m ; i++){
int a, b, d;
cin >> a >> b >> d;
//a--; b--;
if(type[a] == type[b] && type[a] != 'M'){// LL || RR
Add_Edge(a, b, d);Add_Edge(b, a, d);
}else if(type[a] == 'L' && type[b] == 'R'){// LR
Add_Edge(a, b, d + x);Add_Edge(b, a, d + x);
}else if(type[a] == 'R' && type[b] == 'L'){// RL
Add_Edge(a, b, d + x);Add_Edge(b, a, d + x);
}else if(type[a] == 'M' && type[b] == 'L'){// ML
Add_Edge(a, b, d);Add_Edge(b, a, d);
Add_Edge(a + n, b, d + x);Add_Edge(b, a + n, d + x);
}else if(type[a] == 'M' && type[b] == 'R'){// MR
Add_Edge(a, b, d + x);Add_Edge(b, a, d + x);
Add_Edge(a + n, b, d);Add_Edge(b, a + n, d);
}else if(type[a] == 'L' && type[b] == 'M'){// LM
Add_Edge(a, b, d);Add_Edge(b, a, d);
Add_Edge(a, b + n, d + x);Add_Edge(b + n, a, d + x);
}else if(type[a] == 'R' && type[b] == 'M'){// RM
Add_Edge(a, b, d + x);Add_Edge(b, a, d + x);
Add_Edge(a, b + n, d);Add_Edge(b + n, a, d);
}else if(type[a] == 'M' && type[b] == 'M'){// MM
Add_Edge(a, b, d);Add_Edge(b, a, d);
Add_Edge(a + n, b + n, d);Add_Edge(b + n, a + n, d);
Add_Edge(a, b + n, d + x);Add_Edge(b + n, a, d + x);
Add_Edge(a + n, b, d + x);Add_Edge(b, a + n, d + x);
}
}
ll ans = dijkstra();
printf("%lld\n",ans);
}
return 0;
}