Portal

39 篇文章 0 订阅

链接:https://ac.nowcoder.com/acm/contest/5670/A
来源:牛客网

题目描述
You are now in a big factory. The factory could be recognized as a graph with n n n vertices and m m m edges. Every edge has its length. You have k k k missions to do. The i i i-th mission is going to vertex a i a_i ai, picking a block and then sending it to vertex b i b_i bi. You should complete the missions in the order from 1 1 1-st to k k k-th. Initially you are standing at vectex 1 1 1.

You have a gun in your hand. When you are at some vertex u u u, you could shoot the gun at the ground, and then a portal will be built at vertex u u u. When there are two portals in the factory, assuming they are at u u u and v v v, you could transfer between u u u and v v v with no cost(just like an edge connecting u u u and v v v with length 0 0 0).

You also have a remote controller in your hand. It allows you to close a portal whenever you want and wherever you are(closing one portal at a time, not all portals at the same time). What’s more, there could be at most two existing portals. So if you want to create another portal when there exists two, you must use your controller to close one before you create.

You need to find the minimum distance you have to walk in order to complete all k k k missions.
输入描述:
First line contains three positive integers n n n, m m m, k k k separated by spaces.

Next m m m lines, each contains three integers u i u_i ui, v i v_i vi, w i w_i wi, indicating a bidirectional edge connecting vertex u i u_i ui and v i v_i vi with length w i w_i wi.

Next k lines, each contains two intergers a i a_i ai, b i b_i bi, indicating the begin and the end of the i i i-th mission.

1 ≤ n ≤ 300 1 \leq n \leq 300 1n300

1 ≤ m ≤ 40000 1 \leq m \leq 40000 1m40000

1 ≤ k ≤ 300 1 \leq k \leq 300 1k300

1 ≤ u i , v i ≤ n 1 \leq u_i, v_i \leq n 1ui,vin

0 ≤ w i ≤ 1 0 9 0 \leq w_i \leq 10^9 0wi109

1 ≤ a j , b j ≤ n 1 \leq a_j, b_j \leq n 1aj,bjn

The graph is guaranteed to be connected.

输出描述:
Output one integer indicating the minimum distance.

示例1

输入
5 4 2
1 2 1
2 3 1
3 4 1
4 5 1
1 5
2 4
输出
5

说明
Solution for sample 1 1 1: walk from 1 1 1 to 5 5 5, create portals at 2 2 2 and 4 4 4 when passing by. And then walk from 5 5 5 to 4 4 4, then you could use portals to complete the second mission.
示例2

输入
6 10 3
1 1 6
5 6 9
3 5 8
1 4 1
2 4 7
6 6 10
1 4 2
6 5 10
3 5 2
3 1 9
1 5
2 5
4 3
输出
28

示例3

输入
6 10 3
1 1 3
3 1 1
6 2 3
1 6 10
4 1 1
3 1 2
5 6 9
5 4 10
6 3 4
3 4 4
3 5
3 6
6 5
输出
16

由于每次只能传送到一个传送门,并且最多只能同时存在两个传送门,因此只需记录一个传送门的位置。
f [ i ] [ j ] f[i][j] f[i][j]表示当前到达第 i i i个点且传送门在节点 j j j d [ i ] [ j ] d[i][j] d[i][j]表示从节点 i i i到节点 j j j的最短路。
设当前所在节点为 a [ i ] a[i] a[i],下一个节点为 a [ i + 1 ] a[i+1] a[i+1],记录的传送门位置为 p p p
第一种情况为从节点 a [ i ] a[i] a[i]走到 a [ i + 1 ] a[i+1] a[i+1]而不进行其他操作。
则转移方程为:
f [ i + 1 ] [ p ] = m i n ( f [ i + 1 ] [ p ] , f [ i ] [ p ] + d [ a [ i ] ] [ a [ i + 1 ] ] ) f[i+1][p]=min(f[i+1][p],f[i][p]+d[a[i]][a[i+1]]) f[i+1][p]=min(f[i+1][p],f[i][p]+d[a[i]][a[i+1]])
第二种情况为从节点 a [ i ] a[i] a[i]走到节点 q q q,然后从节点 q q q建立传送门传送到 p p p,然后再到节点 a [ i + 1 ] a[i+1] a[i+1]
其中从节点 p p p到节点 a [ i + 1 ] a[i+1] a[i+1]还要分为两种情况:
一种是直接从节点 p p p走到节点 a [ i + 1 ] a[i+1] a[i+1],类似于第一种情况;
另一种是先从节点 p p p走到节点 q ′ q' q在节点 q ′ q' q设一个传送门,然后在从 q ′ q' q走到节点 a [ i + 1 ] a[i+1] a[i+1]
观察发现,从节点 p p p到节点 a [ i + 1 ] a[i+1] a[i+1]的第二种情况直接从节点 a [ i ] a[i] a[i]建立传送门传送到 p p p情况一定不会更差,因此可以不用枚举 q q q
因此转移方程为:
f [ i + 1 ] [ q ] = m i n ( f [ i + 1 ] [ q ] , f [ i ] [ p ] + d [ a [ i ] ] [ q ] + d [ p ] [ a [ i + 1 ] ] ) f[i+1][q]=min(f[i+1][q],f[i][p]+d[a[i]][q]+d[p][a[i+1]]) f[i+1][q]=min(f[i+1][q],f[i][p]+d[a[i]][q]+d[p][a[i+1]])
f [ i + 1 ] [ q ′ ] = m i n ( f [ i + 1 ] [ q ′ ] , f [ i ] [ p ] + d [ p ] [ q ′ ] + d [ q ′ ] [ a [ i + 1 ] ] ) f[i+1][q']=min(f[i+1][q'],f[i][p]+d[p][q']+d[q'][a[i+1]]) f[i+1][q]=min(f[i+1][q],f[i][p]+d[p][q]+d[q][a[i+1]])
时间复杂度为 O ( n 3 ) O(n^3) O(n3)

#include<bits/stdc++.h>

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector<int>
#define pii pair<int,int>
#define mii unordered_map<int,int>
#define msi unordered_map<string,int>
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 305;
ll d[N][N], f[N << 1][N];
int a[N << 1];
int n, m, k;

inline void init() {
    n = qr(), m = qr(), k = qr();
    repi(i, 1, n) {
        repi(j, 1, n)d[i][j] = 4e18;
        d[i][i] = 0;
    }
    repi(i, 0, k * 2)repi(j, 1, n)f[i][j] = 4e18;
    while (m--) {
        int x = qr(), y = qr(), z = qr();
        d[x][y] = d[y][x] = min(d[x][y], 1ll * z);
    }
    repi(i, 1, k * 2)a[i] = qr();
    a[0] = 1, f[0][1] = 0;
}

inline void floyd() {
    repi(u, 1, n) repi(i, 1, n) repi(j, 1, n)d[i][j] = min(d[i][j], d[i][u] + d[u][j]);
}

inline ll dp() {
    repi(i, 1, k * 2)repi(p, 1, n) {
            f[i][p] = min(f[i][p], f[i - 1][p] + d[a[i - 1]][a[i]]);
            repi(q, 1, n) {
                f[i][q] = min(f[i][q], f[i - 1][p] + d[a[i - 1]][q] + d[p][a[i]]);
                f[i][q] = min(f[i][q], f[i - 1][p] + d[p][q] + d[q][a[i]]);
            }
        }
    ll ans = 4e18;
    repi(i, 1, n)ans = min(ans, f[k * 2][i]);
    return ans;
}

int main() {
    init();
    floyd();
    pl(dp());
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_sky123_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值