• 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 imes 10^5). The sum of mm doesn't exceed (4 imes 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 <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    #include <cstring>
    #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<pair<long long,int> >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
    ", min(dijkstra(s, t), dijkstra(s + n, t)));
    	}
        return 0;
    }
    
  • 相关阅读:
    现代软件工程的构建之法
    How do I Check for Duplicate Items in a ListView?
    (转)aspxgridview记录的批量修改
    vs2010简体中文旗舰版智能感知,中文提示,英文提示变化的问题
    (转)怎样成为一名Android开发者
    It’s Not Too Late to Learn How to Code
    (转)手机屏幕VGA QVGA HVGA WVGA区别
    (转)CodeSmithSchemaExplorer类结构详细介绍
    (转)C#控件命名规范
    DataReader 绑定DataGridView的方式
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/13406970.html
Copyright © 2020-2023  润新知