ACM-ICPC 2018 南京赛区网络预赛 L题 L-Magical Girl Haze

题目链接:   https://nanti.jisuanke.com/t/31001

L-Magical Girl Haze

 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 256MB Problem Description 


There are N cities in the country, and M directional roads from u to v(1<=u, v<=n).Every road has a distance ci. Haze is a Magical Girl that lives in City 1, she can choose no more than K roads and make their distances become 0. Now she wants to go to City N, please help her calculate the minimum distance.    Input 
The first line has one integer T(1<=T<=5), then following T cases. For each test case, the first line has three integers N, M and K. Then the following M lines each line has three integers, describe a road, Ui, Vi, Ci. There might be multiple edges between u and v.  It is guaranteed that N<=100000, M<=200000, K<=10, 0<=c[i]<=1e9. There is at least one path between City 1 and City N. Output 


For each test case, print the minimum distance.

Sample Input 
1

5 6 1

1 2 2

1 3 4

2 4 3

3 4 1

3 5 6

4 5 2

Sample Output 

 

题目意思很简单,最短路问题,不同之处在于,有K次“免费”的机会。也就是在部分边权值可变为0的情况下,求最短路的问题。

 

对于这种要求的最短路问题,采用分层图+Dijkstra。不说了,今天网络赛又是签到滚蛋,心累。。。。。

直接上代码:

请叫我模板怪


#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N=1e6+10,M=4e7+10,inf=1e9+10;
const ll INF=1e18+10;
struct is
{
    int v,w;
    int next;
}edge[N*4];
int head[N*4],si;
int flag[N][23];
int d[N][23];
struct point
{
    int pos,dis;
    point(int a,int b){pos=b;dis=a;}
    friend bool operator <(point x,point y)
    {
        return x.dis>y.dis;
    }
};
void add(int u,int v,int w)
{
    si++;
    edge[si].v=v;
    edge[si].w=w;
    edge[si].next=head[u];
    head[u]=si;
}
void dij(int n,int k)
{
    priority_queue<point>q;
    point a(0,1);
    q.push(a);
    while(!q.empty())
    {
        point v=q.top();
        q.pop();
        int x=(v.pos)%(n+1);
        int y=(v.pos)/(n+1);
        if(flag[x][y])continue;
        flag[x][y]=1;
        for(int i=head[x];i;i=edge[i].next)
        {
            int vv=edge[i].v;
            if(d[vv][y]>d[x][y]+edge[i].w)
            {
                d[vv][y]=d[x][y]+edge[i].w;
                q.push(point(d[vv][y],y*(n+1)+vv));
            }
            if(y==k)continue;
            if(d[vv][y+1]>d[x][y])
            {
                d[vv][y+1]=d[x][y];
                q.push(point(d[vv][y+1],(y+1)*(n+1)+vv));
            }
        }
    }
    printf("%d\n",d[n][k]);
}
void init()
{
    si=0;
    memset(head,0,sizeof(head));
    memset(flag,0,sizeof(flag));
    for(int i=1;i<N;i++)
    for(int t=0;t<21;t++)
    d[i][t]=inf;
    d[1][0]=0;
}
int main()
{
    int x,y,z,i,t;
    int T;
    scanf("%d",&T);

    while(T--)
    {scanf("%d%d%d",&x,&y,&z);
        init();
        for(i=0;i<y;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            //add(v,u,w);
        }
        dij(x,z);
    }
    return 0;
}

欢迎讨论交流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值