HDU6805 Deliver the Cake(最短路/思维)

It is Zhang3's birthday! Zhang3 has bought a birthday cake and now it's time to take it home.

There are n villages, labeled 1,2,…,n. There are m bidirectional roads, the ith of which connects village \(a_i\), \(b_i\) and it is \(d_i\) meter(s) long.

The bakery locates at village s and Zhang3's home locates at village t. So Zhang3 wants to carry the cake from s to t. She can carry the cake either with her left hand or with her right hand. She can switch to the other hand during the trip, which takes extra xx

second(s) each time (when she's performing this action, she must stay in her place). Switching is allowed at any place, including the middle of the roads. She can do this as many times as she like, or don't do it at all.

Some villages are LEFT. When Zhang3 is at a LEFT village, she must carry the cake with her left hand at the moment. In the same way, some other villages are RIGHT, she must carry with her right hand when she's at these villages. The rest villages are called MIDDLE. There's no special rules at MIDDLE villages.

Zhang3 can start and finish with any hand carrying the cake. However, if s or t is not MIDDLE, their special rules must be followed.

Please help Zhang3 find a way to take the cake home, with the minimum amount of spent time.

Input

The first line of the input gives the number of test cases, T(1≤T≤100)T(1≤T≤100).

T test cases follow.

For each test case, the first line contains five integers n,m,s,t,x(\(1≤n≤10^5,1≤m≤2×10^5,1≤x≤10^9\))

, representing the number of villages, the number of roads, the bakery's location, home's location, and the time spent for each switching.

The next line contains a string of length n, describing the type of each village. The ith character is either L representing village i is LEFT, or M representing MIDDLE, or R representing RIGHT.

Finally, m lines follow, the ith of which contains three integers a**i,b**i,d**i(1≤d**i\(10^9\))ai,bi,di(1≤di≤\(10^9\)), denoting a road connecting village \(a_i\) and \(b_i\)

of length \(d_i\). It is guaranteed that t can be reached from s.

The sum of n in all test cases doesn't exceed \(2\times 10^5\). The sum of mm doesn't exceed \(4\times 10^5\).

Output

For each test case, print a line with an integer, representing the minimum amount of spent time (in seconds).

Sample Input

1
3 3 1 3 100
LRM
1 2 10
2 3 10
1 3 100

Sample Output

100

哎...比赛时思路其实差不多了...理论上先把点的关系转化为边权上也是没问题的啊...不知道为什么跑不对...

如果两个点u,v都是L或者都是R或者一个L一个R,这样的话从u到v的时间其实已经确定了。关键是MIDDLE。暴力想法是枚举每个MIDDLE为L或者R,这样显然会爆炸,那么不妨把一个MIDDLE转化为一个L和一个R(对应到数组里分别是u和u + n, v 和 v + n),分别建边,这样直接在扩充的图上跑Dijkstra(以s和s+n为原点),最后输出min(d[t], d[t + n])即可。注意,为了方便起见,可以把L转化为两个L,R转化为两个R。

#include 
#include 
#include 
#include 
#include 
#include 
#define N 400005
#define M 800005
using namespace std;
int n, m, s, t, xx;
long long d[2 * N];
int head[N * 2],ver[4 * M],edge[4 * M], Next[4 * M];//开两倍存储双向边 
bool v[N * 2];
int tot=0;
priority_queue >q;//这里别忘long long 
int hand[2 * N];
void add(int x,int y,int z)
{
    ver[++tot]=y;
    edge[tot]=z;
    Next[tot]=head[x];
    head[x]=tot;
}
long long dijkstra(int s, int t)
{
	long long ans = 1e18;
    for(int i = 1; i <= 2 * n; i++) d[i] = 1e18;
    memset(v, 0, sizeof(v));
    d[s]=0;
    q.push(make_pair(0,s));
    int i,j;
    while(q.size())
    {
        int x=q.top().second;
        q.pop();
        if(v[x])continue;
        v[x]=1;
        for(i=head[x];i;i=Next[i])
        {
            int y=ver[i],z=edge[i];
            if(hand[x] != hand[y]) z += xx;//是否要换手 
            if(d[y]>d[x]+z)
            {
                d[y]=d[x]+1ll * z;
                q.push(make_pair(-d[y],y));
            }
        }
    }
	return min(d[t], d[t + n]);
}
signed main()
{
	//freopen("D.in","r",stdin);
   	//freopen("my.ans","w",stdout);
    int Case;
    cin >> 	Case;
    while(Case--)
    {
    	tot = 0;
    	for(int i = 1; i <= 2 * n; i++) head[i] = 0;
    	scanf("%d%d%d%d%d", &n, &m, &s, &t, &xx);
    	string ss;
    	cin >> ss;
    	for(int i = 0; i < ss.size(); i++)
    	{
    		if(ss[i] == 'L')
    		{
    			hand[i + 1] = hand[i + 1 + n] = 0;
			}
			else if(ss[i] == 'R')
    		{
    			hand[i + 1] = hand[i + 1 + n] = 1;
			}
			else
			{
				hand[i + 1] = 0;
				hand[i + 1 + n] = 1;
			}
		}
		for(int i = 1; i <= m; i++)
		{
			int u, v, w;
			scanf("%d%d%d", &u, &v, &w);
			add(u, v, w);
			add(v, u, w);
			add(u + n, v, w);
			add(v, u + n, w);
			add(u, v + n, w);
			add(v + n, u, w);
			add(u + n, v + n, w);
			add(v + n, u + n, w);
		}
		printf("%lld\n", min(dijkstra(s, t), dijkstra(s + n, t)));
	}
    return 0;
}

你可能感兴趣的:(HDU6805 Deliver the Cake(最短路/思维))