Magical Girl Haze(2018南京网络赛L题,分层图最短路)

南京网络赛 - L

Magical Girl Haze

There are N cities in the country, and MM 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 minimumdistance.

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≤Ci≤1e9. There is at least one path between City 1 and City N.

Output
For each test case, print the minimum distance.

样例输入

1
5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2

样例输出

3

分析:

求最短路,可以选择k个边权变为0,是分层图最短路的板子题。抄板子一直不过,可能会有两个问题,一个是没开longlong,一个是我把单向边存成了双向边,找了我好久。网上很多题解说要去重边,而实际上根本不需要,对结果没有任何影响。还有就是数组尽量开大,防止段错误。

参考代码:

模板1:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
typedef long long ll;
#define pii pair<ll,int>
const ll inf=0x3f3f3f3f;
const int MAXN=4500005;
using namespace std;

struct Edge {
    int to,next;
    ll w;
} edge[MAXN];
int head[MAXN],tot;
ll dis[MAXN],ans;
int vis[MAXN];
int n,m,s,t,k;

void init() {
    tot=0;
    memset(head,-1,sizeof(head));
    memset(dis,inf,sizeof(dis));
    memset(vis,0,sizeof(vis));
}

void addedge(int u,int v,ll w) {
    edge[tot].to=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}

void dijkstra() {
    priority_queue<pii,vector<pii>,greater<pii> > q;
    dis[s]=0; q.push({dis[s],s});
    while(!q.empty()) {
        int now=q.top().second;
        q.pop();
        if (vis[now]) continue;
        vis[now]=1;
        for (int i=head[now];i!=-1;i=edge[i].next) {
            int v=edge[i].to;
            if(!vis[v]&&dis[v]>dis[now]+edge[i].w) {
                dis[v]=dis[now]+edge[i].w;
                q.push({dis[v],v});
            }
        }
    }
}

int main() {
    int T,u,v; ll w;
    scanf("%d",&T);
    while(T--) {
        init();
        cin >> n >> m >> k;
        // 起点为1,终点为n
        s=1; t=n;
        for (int i=1;i<=m;i++) {
            scanf("%d%d%lld",&u,&v,&w);
            for (int j=0;j<=k;j++) {
            	// 双向边就GG,不需要去重边
                addedge(u+j*n,v+j*n,w);
                //addedge(v+j*n,u+j*n,w);
                if (j!=k) {
                    addedge(u+j*n,v+(j+1)*n,0);
                    //addedge(v+j*n,u+(j+1)*n,0);
                }
            }
        }
        ans=1e18;
        dijkstra();
        for (int i=0;i<=k;i++)
            ans=min(ans,dis[t+i*n]);
        cout << ans << endl;
    }
    return 0;
}

模板2:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
typedef long long ll;
#define pii pair<ll, int>
const ll inf=0x3f3f3f3f;
const int MAXN=300005;
using namespace std;

struct node {
    int x,y;
    ll w;
    node(){}
    node(int _x,int _y,ll _w) {
        x=_x; y=_y; w=_w;
    }
    friend bool operator < (const node a,const node b) {
        return a.w > b.w;
    }
};
struct Edge {
    int to,next;
    ll w;
} edge[MAXN*4];
int head[MAXN*4],tot;
ll dis[MAXN][15],ans;
int vis[MAXN][15];
int n,m,s,t,k;

void init() {
    tot=0;
    memset(head,-1,sizeof(head));
    memset(dis,inf,sizeof(dis));
    memset(vis,0,sizeof(vis));
}

void addedge(int u,int v,ll w) {
    edge[tot].to=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}

void dijkstra() {
    priority_queue<node> q;
    dis[s][0]=0;
    q.push(node(s,0,0));
    while(!q.empty()) {
        int x=q.top().x,y=q.top().y;
        q.pop();
        if (vis[x][y]) continue;
        vis[x][y]=1;
        for (int i=head[x];i!=-1;i=edge[i].next) {
            int to=edge[i].to;
            if (dis[x][y]+edge[i].w<dis[to][y]) {
                dis[to][y]=dis[x][y]+edge[i].w;
                q.push(node(to,y,dis[to][y]));
            }
            if (y+1<=k && dis[x][y]<dis[to][y+1]) {
                dis[to][y+1]=dis[x][y];
                q.push(node(to,y+1,dis[to][y+1]));
            }
        }
    }
}

int main() {
    int T,u,v; ll w;
    scanf("%d",&T);
    while(T--) {
        init();
        cin >> n >> m >> k;
        s=1; t=n;
        for (int i=1;i<=m;i++) {
            scanf("%d%d%lld",&u,&v,&w);
            addedge(u,v,w);
        }
        ans=1e18;
        dijkstra();
        for (int i=0;i<=k;i++)
            ans=min(ans,dis[n][i]);
        cout << ans << endl;
    }
    return 0;
}

发布了136 篇原创文章 · 获赞 33 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Radium_1209/article/details/100127485