列表

详情


NC20183. [JSOI2010]旅行

描述

WJJ喜欢旅游,这次她打算去一个据说有很多漂亮瀑布的山谷玩。 WJJ事先得到了一张地图,上面标注了N(1 ≤ N ≤ 50)个小动物的聚居地,也就是一个个的小村落。其中第1个村 庄是WJJ现在住的地方,第N个村庄是WJJ打算去的地方。
这些村庄之间有M(1 ≤ M ≤ 150)条双向道路连接着,第j 条双向道路恰好直接连接两个小村庄A,B,长度为C(1 ≤ A,B ≤ N,Ai < > B, 1 ≤ C ≤ 1000)。道路有的是隧道,有的是栈桥,地图上那些看起来在村庄之外交叉的路实际上并不相交——也就是说,如果把这些小村落和双向道路构成的道路网看作图论意义上的图,我们不保证它是平面图,也不保证它没有重边。
不过,有一点还是可以保 证的:WJJ细心地验证过,从它居住的村落一定能走到她想去的那个山谷。 在WJJ所在的神奇世界中,每只小动物都可以借助仙人掌来施放魔法,其中之一是,交换世界中任意两条双向道路 的长度,同时保持其他道路的长度不变。
按WJJ目前的魔法水平,她最多能使用K(1 ≤ K ≤ 20)次这种道路长度交换魔法。可惜的是,由于仙人掌刺比较多,WJJ并不打算带着它旅行,于是她会在家里完成想要的道路交换后再出门。假设WJI的旅行途中不会有其他小动物进行道路交换来破坏她设计好的路线。
为了尽快达到目的地,WJJ希望她需要走的总距离越短越好。也就是说,使用最多K次魔法后,从村落1到村落N的最短距离是多少?

输入描述

第1行:3个用空格隔开的整数N,M,K
第2..M+1行:每行是3个整数,用空格隔开,分别表示A,B C

输出描述

1个整数,表示使用最多K次魔法后,村落1和村落N之间的最短距离。

示例1

输入:

5  5  2
1  2  10
2  5  10
1  3  4
3  4  2
4  5  1

输出:

3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 378ms, 内存消耗: 12132K, 提交时间: 2020-06-17 09:12:40

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int MX=59;
struct node{
    int u,v,val;
    bool operator<(const node &a)const{
        return val<a.val;
    }
}t[159];
vector<int> vec[MX];
int n,m,k;

struct Node{
    int i,j,k;
};
int ans,dis[59][159][159],vis[59][159][159];
void work(int fr){
    queue<Node> que;
    que.push({1,0,0});
    memset(dis,inf,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[1][0][0]=0;
    vis[1][0][0]=1;
    while( !que.empty() ){
        Node temp=que.front();
        que.pop();
        int ii=temp.i,jj=temp.j,kk=temp.k;
        vis[ii][jj][kk]=0;
        for( int i=0 ; i<vec[ii].size() ; i++ ){
            int num=vec[ii][i];
            int son=(t[num].u==ii?t[num].v:t[num].u);
            int val=t[num].val;
            if( num<=fr ){
                if( jj<fr && dis[son][jj+1][kk]>dis[ii][jj][kk]+t[jj+1].val ){
                    dis[son][jj+1][kk]=dis[ii][jj][kk]+t[jj+1].val;
                    if( !vis[son][jj+1][kk] ){
                        vis[son][jj+1][kk]=1;
                        que.push({son,jj+1,kk});
                    }
                }
            }
            else{
                if( dis[son][jj][kk]>dis[ii][jj][kk]+val ){
                    dis[son][jj][kk]=dis[ii][jj][kk]+val;
                    if( !vis[son][jj][kk] ){
                        vis[son][jj][kk]=1;
                        que.push({son,jj,kk});
                    }
                }
                if( kk<k && jj<fr && dis[son][jj+1][kk+1]>dis[ii][jj][kk]+t[jj+1].val ){
                    dis[son][jj+1][kk+1]=dis[ii][jj][kk]+t[jj+1].val;
                    if( !vis[son][jj+1][kk+1] ){
                        vis[son][jj+1][kk+1]=1;
                        que.push({son,jj+1,kk+1});
                    }
                }
            }
        }
    }
    for( int i=1 ; i<=k ; i++ )
        ans=min(ans,dis[n][fr][i]);
}

int main()
{
//    freopen("input.txt","r",stdin);
    scanf("%d %d %d",&n,&m,&k);
    for( int i=1 ; i<=m ; i++ )
        scanf("%d %d %d",&t[i].u,&t[i].v,&t[i].val);
    sort(t+1,t+1+m);
    for( int i=1 ; i<=m ; i++ ){
        vec[t[i].u].push_back(i);
        vec[t[i].v].push_back(i);
    }
    ans=inf;
    for( int i=1 ; i<=m ; i++ )
        work(i);
    printf("%d\n",ans);
    return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 264ms, 内存消耗: 2384K, 提交时间: 2023-06-11 21:56:16

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N=60,M=160,INF=0x3f3f3f3f;
int n,m,K,ans;
int dist[N][M][25],vis[N][M][25];
struct Edge{
    int u,v,w;
    bool operator<(const Edge& b) const {return w<b.w;}
}edge[M];
vector<int> mm[N];
void spfa(int sum) {
    memset(dist,0x3f,sizeof dist);
    memset(vis,0,sizeof vis);
    queue<vector<int>> q;
    q.push({1,0,0});
    dist[1][0][0]=0;
    while(!q.empty()) {
        auto t=q.front();q.pop();
        int u=t[0],l=t[1],k=t[2];
        vis[u][l][k]=0;
        for(int i=0;i<mm[u].size();i++) {
            int s=mm[u][i];
            int v=(u==edge[s].u?edge[s].v:edge[s].u);
            if(s<=sum) {
                if(dist[v][l+1][k]>dist[u][l][k]+edge[l+1].w && l<sum) {
                    dist[v][l+1][k]=dist[u][l][k]+edge[l+1].w;
                    if(!vis[v][l+1][k]) {
                        vis[v][l+1][k]=1;
                        q.push({v,l+1,k});
                    }
                }
            }else{
                if(dist[v][l][k]>dist[u][l][k]+edge[s].w) {
                    dist[v][l][k]=dist[u][l][k]+edge[s].w;
                    if(!vis[v][l][k]) {
                        vis[v][l][k]=1;
                        q.push({v,l,k});
                    }
                }
                if(dist[v][l+1][k+1]>dist[u][l][k]+edge[l+1].w && l<sum && k<K) {
                    dist[v][l+1][k+1]=dist[u][l][k]+edge[l+1].w;
                    if(!vis[v][l+1][k+1]) {
                        vis[v][l+1][k+1]=1;
                        q.push({v,l+1,k+1});
                    }
                }
            }
        }
    }
    for(int i=0;i<=K;i++) ans=min(ans,dist[n][sum][i]);
}
int main() {
    scanf("%d%d%d",&n,&m,&K);
    for(int i=1;i<=m;i++) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
    sort(edge+1,edge+m+1);
    for(int i=1;i<=m;i++) {
        mm[edge[i].u].push_back(i);
        mm[edge[i].v].push_back(i);
    }
    ans=INF;
    for(int i=0;i<=m;i++)
        spfa(i);
    printf("%d\n",ans);
    return 0;
}

上一题