zoukankan      html  css  js  c++  java
  • HDU-3499Flight (分层图dijkstra)

    一开始想的并查集(我一定是脑子坏掉了),晚上听学姐讲题才知道就是dijkstra两层;

    题意:有一次机会能使一条边的权值变为原来的一半,询问从s到e的最短路。

    将dis数组开成二维,第一维表示从源点到点i的路径长度,第二维表示是否使用了该次机会,并以此不断更新。

    用map将字符串转为int,剩下的就是dijkstra+优先队列;

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<map>
    #include<queue>
    #define ll long long
    #define INF 1e18
    using namespace std;
    
    const int N = 1e5+10;
    const int M = 5e5+10;
    int tot,m,n;
    
    struct Edge
    {
        int v, cost, next;
    }edge[M];
    
    struct qnode
    {
        int loc,level;
        ll dis;
        bool operator < (const qnode &t) const {
            return dis > t. dis;
        }
        qnode(int a=0,int b=0,ll c=0){
            loc=a,level=b,dis=c;
        }
    }d[N][2];
    
    int head[M];
    bool vis[N][2];
    
    void addedge(int u, int v, ll w)
    {
        edge[tot]. v = v;
        edge[tot]. cost = w;
        edge[tot]. next = head[u];
        head[u] = tot ++;
    }
    
    void dijkstra(int st)
    {
        memset(vis, 0, sizeof(vis));
        for(int i=1;i<=n;i++){
            for(int j=0;j<=1;j++){
                d[i][j].dis=INF;
            }
        }
        d[st][0].dis = 0;
        priority_queue <qnode> q;
        q. push(qnode(st,0,0));
        while(! q. empty()){
            qnode t = q. top();
            q. pop();
            int t1=t.loc,t2=t.level;
            if(vis[t1][t2])continue;
            vis[t1][t2]=true;
            for(int i = head[t1]; i != -1; i = edge[i]. next){
                int v = edge[i]. v;
                int cost = edge[i]. cost;
                if( d[v][t2].dis > d[t1][t2].dis + cost){
                    d[v][t2].dis = d[t1][t2].dis + cost;
                    q. push(qnode(v,t2,d[v][t2].dis));
                }
                if(t2==0&&d[v][t2+1].dis>d[t1][t2].dis+cost/2){        //分别记录每一段是半价的价格
                    d[v][t2+1].dis=d[t1][t2].dis+cost/2;
                    q.push(qnode(v,t2+1,d[v][t2+1].dis));
                }
            }
        }
    }
    
    
    int main(){
        while(scanf("%d%d", &n, &m)!=EOF){
            string a,b;
            map<string,int> cnt;
            cnt.clear();
            ll c;
            tot = 1;
            int k=1;
            memset(head, -1, sizeof(head));
            while(m --){
                cin>>a>>b>>c;
                if(!cnt[a])cnt[a]=k++;
                if(!cnt[b])cnt[b]=k++;
                addedge(cnt[a], cnt[b], c);
            }
            cin>>a>>b;
            if(!cnt[a])cnt[a]=k++;
            if(!cnt[b])cnt[b]=k++;
            if(m==0) {
                printf("-1
    ");
                continue;
            }
            dijkstra(cnt[a]);
            ll ans=min(d[cnt[b]][0].dis,d[cnt[b]][1].dis);
            if(ans==INF) printf("-1
    ");
            else printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    (三十九)golang--反序列化
    (三十八)golang--json(对切片、map、结构体进行序列化)
    (三十七)golang--如何获取命令行参数
    (三十六)golang--文件的基本操作
    golang实战--客户信息管理系统
    Linux系统的LOG日志文件及入侵后日志的清除
    Linux下清除系统日志方法
    linux log日志解析
    linux添加开机自启动脚本示例详解
    linux添加开机启动项的方法介绍
  • 原文地址:https://www.cnblogs.com/lilibuxiangtle/p/11347076.html
Copyright © 2011-2022 走看看