一开始想的并查集(我一定是脑子坏掉了),晚上听学姐讲题才知道就是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\n");
            continue;
        }
        dijkstra(cnt[a]);
        ll ans=min(d[cnt[b]][0].dis,d[cnt[b]][1].dis);
        if(ans==INF) printf("-1\n");
        else printf("%lld\n",ans);
    }
    return 0;
}