ACM-ICPC 2018 南京赛区网络预赛 L Magical Girl Haze 分层图最短路 + Dijkstra

1.题意:给出n个 城市,m条路的有向图,每条路有路费,但是可以选择k条路免费通过,问从城市1到达城市n的最低花费。

2.分析: 分层图最短路问题,用dist [i] [j] 表示到达 i 城市,免费了j条路时的最低花费,那么从当前点到达下一个点时就有两种选择:

(1)两点间的这条路不免费,dist[to][j] = dist[i][j] + val;

(2)若j+1<=k 则这条路可以选择免费 : dist[to][j+1] = dist [i] [j] + 0;

最后判断dist[n][1~k]的最小(因为dist[n][k]不一定是最小的)

3.代码:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long LL;
const int maxn = 100000 + 7;
struct Edge{
   int to,next;
   LL val;
}edge[maxn*2];
LL dist[maxn][11],head[maxn];
bool vis[maxn][11];
int n,m,k,tot;
void addEdge(int a,int b,LL c){
   edge[tot].to = b;edge[tot].next = head[a];edge[tot].val = c;head[a] = tot++;
}
struct Node{
   int p,x;//当前点,当前免费次数,当前总花费
   LL v;
   bool operator <(const Node &another)const{
        return v>another.v;
   }
   Node(int a,int b,LL c):p(a),x(b),v(c) {}
};
void Dijkstra(int s){
    memset(dist,INF,sizeof(dist));
    for(int i = 0;i<=k;i++)dist[s][i] = 0;
    priority_queue<Node> que;
    que.push(Node(s,0,0));
    while(!que.empty()){
        Node node = que.top();
        que.pop();
        if(vis[node.p][node.x])continue;
        vis[node.p][node.x] = 1;//标记
        int u = node.p;
        int num = node.x;
        for(int i = head[u];~i;i = edge[i].next){
            if(!vis[edge[i].to][num]&&edge[i].val + dist[u][num]<dist[edge[i].to][num]){
                dist[edge[i].to][num] = edge[i].val + dist[u][num];//这条路不免费
                que.push(Node(edge[i].to,num,dist[edge[i].to][num]));
            }
            if(!vis[edge[i].to][num+1]&&num<k&&dist[edge[i].to][num+1]>dist[u][num]){
                dist[edge[i].to][num+1]=dist[u][num];//这条路免费
                que.push(Node(edge[i].to,num+1,dist[edge[i].to][num+1]));
            }
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        tot = 0;
        memset(vis,0,sizeof(vis));
        memset(head,-1,sizeof(head));
        scanf("%d%d%d",&n,&m,&k);
        for(int i = 0;i<m;i++){
            int  a,b;
            LL v;
            scanf("%d%d%lld",&a,&b,&v);
            addEdge(a,b,v);//有向图链式前向星
        }
        Dijkstra(1);
        LL minn = INF;
        for(int i = 0;i<=k;i++){//取最小
                minn = min(minn,dist[n][i]);
        }
        printf("%lld\n",minn);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40772692/article/details/82377789
今日推荐