宫水三叶喜欢旅游。
三叶来到了一个 n n n 个点的城市,点与点之间有边相连,边有长度,即三叶通过所需时间。
三叶制定了一份旅游计划表。
计划表上总共包含 k k k 个计划,每个计划可以用两个节点 a i , b i a_i,b_i ai,bi 来描述。因为两个节点有一定联系,所以第 i i i 个计划是先到达节点 a i a_i ai ,然后到达节点 b i b_i bi 。
三叶认为计划一定要按顺序来完成,所以在还没完成第 i i i 个计划时,是不会进行第 i + 1 i+1 i+1 个计划的。
三叶通过一些获得了两个传送门。每一次三叶到达一个节点 x x x 后可以做以下操作。
- 三叶可以不操作
- 三叶可以选择图上任意一个传送门,并将其收回。
- 如果 x x x 没有传送门,并且图上的传送门个数不到 2 2 2 个,那么三叶可以在 x x x 上设立传送门。
- 如果 x x x 有传送门,并且图上还有一个传送门在 y y y ,那么三叶可以不花费任何时间从 x x x 走到 y y y 。当然,三叶也可以放弃这次机会。
以上操作均不耗时。
三叶一开始在节点 1 1 1 。那么请问,三叶完成所有计划的最小时间是多少。
第一行,三个整数 n , m , k n,m,k n,m,k ,表示点数,边数,计划数。
接下来 m m m 行,每行三个整数 u i , v i , w i u_i,v_i,w_i ui,vi,wi ,表示一条连接 u i , v i u_i,v_i ui,vi 的长度为 w i w_i wi 的双向边。
接下来 k k k 行,每行两个整数 a i , b i a_i,b_i ai,bi ,描述一个计划。
输出一行,表示最小花费时间。
样例输入 1
5 4 2
1 2 1
2 3 1
3 4 1
4 5 1
1 5
2 4
样例输出 1
5
样例输入 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
样例输出 2
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
样例输出 3
16
样例数据 4
见下发文件。
本题采用捆绑测试。
对于所有数据,满足 1 ≤ n , k ≤ 300 , 1 ≤ m ≤ 4 × 1 0 4 , 0 ≤ w i ≤ 1 0 9 1\le n,k \le 300,1\le m \le 4\times 10^4,0\le w_i \le 10^9 1≤n,k≤300,1≤m≤4×104,0≤wi≤109。
保证图为连通图。
子任务编号 | n , k n,k n,k | 分值 |
---|---|---|
1 1 1 | ≤ 40 \le 40 ≤40 | 30 30 30 |
2 2 2 | ≤ 80 \le 80 ≤80 | 30 30 30 |
3 3 3 | ≤ 300 \le 300 ≤300 | 40 40 40 |
大水题,直接DP但得发现只有一个传送门有用。
#include<bits/stdc++.h>
#define N 305
#define M 40004
typedef long long ll;
using namespace std;
const ll inf=1e16;
inline int read(){
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){
if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+s-'0';s=getchar();}
return x*f;
}
ll g[N][N],f[2][N],m1;
int a[N<<1],b[N<<1];
int main(){
// freopen("data.in","r",stdin);
// freopen("path.out","w",stdout);
int n=read(),m=read(),k=read();
for(int i=1;i<=n;++i)for(int j=i+1;j<=n;++j)g[i][j]=g[j][i]=inf;
for(int i=1;i<=m;++i){
int x=read(),y=read();ll z=read();
g[x][y]=min(g[x][y],z);g[y][x]=min(g[y][x],z);
}
a[1]=1;
int le=1;
for(int i=1;i<=k;++i){
int x=read(),y=read();
b[le]=x;a[++le]=x,b[le]=y;a[++le]=y;
}
for(int z=1;z<=n;++z){
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
g[i][j]=min(g[i][j],g[i][z]+g[z][j]);
}
}
}
le--;k=le;
for(int i=1;i<=n;++i)f[0][i]=inf;
f[0][1]=0;
for(int i=1;i<=k;++i){
int now=i&1,x=a[i],y=b[i];
for(int j=1;j<=n;++j)f[now][j]=inf;m1=inf;
for(int j=1;j<=n;++j)m1=min(m1,f[now^1][j]);
for(int j=1;j<=n;++j){
f[now][j]=min(f[now][j],g[x][y]+f[now^1][j]);
}
for(int j=1;j<=n;++j){
f[now][j]=min(f[now][j],g[x][j]+g[j][y]+m1);
}
for(int j=1;j<=n;++j){
f[now][j]=min(f[now][j],f[now^1][j]+g[j][y]);
}
for(int j=1;j<=n;++j)for(int h=1;h<=n;++h){
f[now][j]=min(f[now][j],g[x][j]+g[h][y]+f[now^1][h]);
}
for(int j=1;j<=n;++j)for(int h=1;h<=n;++h){
f[now][j]=min(f[now][j],g[h][j]+g[j][y]+f[now^1][h]);
}
}
ll ans=inf;
for(int j=1;j<=n;++j)ans=min(ans,f[k&1][j]);
printf("%lld\n",ans);
return 0;
}