ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze (拆点+最短路)

https://nanti.jisuanke.com/t/31001

题意:

有n个城市,m条有向路,最多选取k条路的权值为0,求1到n的最短路。

 

思路:

我们可以当每个点分成k 层,同一层的点的权值为w,到下一层的权值为0,这样建图,就能保证最短k条边的权值为0,然后跑最短路。

 

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e6+10;
const int maxm=5e6+10;
const ll inf=1e18;
struct node
{
    int u,v,w,next;
}edge[maxm];
int head[maxn];
int n,m,k;
int cnt;
struct Node
{
    int id;
    ll cost;
}dis[maxn];
bool operator<(Node a,Node b)
{
    return a.cost>b.cost;
}

void init()
{
    cnt=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)
{
    for(int i=0;i<=k;i++)
    {
        edge[cnt].u=u+i*n;
        edge[cnt].v=v+i*n;
        edge[cnt].w=w;
        edge[cnt].next=head[u+i*n];
        head[u+i*n]=cnt++;
    }
    for(int i=0;i<k;i++)
    {
        edge[cnt].u=u+i*n;
        edge[cnt].v=v+(i+1)*n;
        edge[cnt].w=0;
        edge[cnt].next=head[u+i*n];
        head[u+i*n]=cnt++;
    }
}
bool vis[maxn];
void dij()
{
    for(int i=1;i<=n*k+n;i++)
        dis[i].id=i,dis[i].cost=inf;
    dis[1].cost=0;
    priority_queue<Node>q;
    q.push(dis[1]);
    while(!q.empty())
    {
        Node u=q.top();
        q.pop();
        for(int i=head[u.id];i!=-1;i=edge[i].next)
        {
            int v=edge[i].v;
            int w=edge[i].w;
            if(dis[v].cost>dis[u.id].cost+w)
                dis[v].cost=dis[u.id].cost+w,q.push(dis[v]);
        }
    }

}
int main()
{
    int T;
    scanf("%d",&T);
     while(T--)
     {
         scanf("%d%d%d",&n,&m,&k);
         init();
         int u,v,w;
         for(int i=0;i<m;i++)
         {
             scanf("%d%d%d",&u,&v,&w);
             addedge(u,v,w);
         }
         dij();
         printf("%lld\n",dis[n*k+n].cost);
     }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值