• 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
    ",ans);
        }
    
        return 0;
    }
  • 相关阅读:
    一个故事看懂CPU的SIMD技术
    MySQL 表数据多久刷一次盘?
    java高级用法之:无所不能的java,本地方法调用实况
    java高级用法之:调用本地方法的利器JNA
    网络协议之:socket协议详解之Datagram Socket
    网络协议之:socket协议详解之Socket和Stream Socket
    netty系列之:java中的base64编码器
    网络协议之:socket协议详解之Unix domain Socket
    git 常用命令
    在线curl转换
  • 原文地址:https://www.cnblogs.com/ecustlegendn324/p/13446699.html
Copyright © 2020-2023  润新知