1. 程式人生 > >P2939 [USACO09FEB]改造路Revamping Trails【題解】

P2939 [USACO09FEB]改造路Revamping Trails【題解】

題意翻譯

約翰一共有 N N 個牧場.由 M M 條佈滿塵埃的小徑連線.小徑可 以雙向通行.每天早上約翰從牧場 1

1 出發到牧場 N N 去給奶牛檢查身體.

通過每條小徑都需要消耗一定的時間.約翰打算升級其中 K K 條小徑,使之成為高速公路.在高速公路上的通行幾乎是瞬間完成的,所以高速公路的通行時間為 0

0 .

請幫助約翰決定對哪些小徑進行升級,使他每天從 1 1 號牧場到第 N N 號牧場所花的時間最短

題目描述

Farmer John dutifully checks on the cows every day. He traverses some of the M (1 <= M <= 50,000) trails conveniently numbered 1…M from pasture 1 all the way out to pasture N (a journey which is always possible for trail maps given in the test data). The N (1 <= N <= 10,000) pastures conveniently numbered 1…N on Farmer John’s farm are currently connected by bidirectional dirt trails. Each trail i connects pastures P1_i and P2_i (1 <= P1_i <= N; 1 <= P2_i <= N) and requires T_i (1 <= T_i <= 1,000,000) units of time to traverse.

He wants to revamp some of the trails on his farm to save time on his long journey. Specifically, he will choose K (1 <= K <= 20) trails to turn into highways, which will effectively reduce the trail’s traversal time to 0. Help FJ decide which trails to revamp to minimize the resulting time of getting from pasture 1 to N.

TIME LIMIT: 2 seconds

輸入輸出格式

輸入格式:

  • Line 1: Three space-separated integers: N, M, and K

  • Lines 2…M+1: Line i+1 describes trail i with three space-separated integers: P1_i, P2_i, and T_i

輸出格式:

  • Line 1: The length of the shortest path after revamping no more than K edges
輸入輸出樣例
輸入樣例#1:

4 4 1
1 2 10
2 4 10
1 3 1
3 4 100

輸出樣例#1: 複製

1

說明

K is 1; revamp trail 3->4 to take time 0 instead of 100. The new shortest path is 1->3->4, total traversal time now 1.


這道題是分層圖最短路問題,顧名思義,就是在分層圖上跑最短路

這樣的題好像都挺裸的

剛剛寫了一篇類似的,不懂可以看這個Luogu P4568 [JLOI2011]飛行路線【題解】

這兩個題除了輸入輸出就可以說是一樣的。

直接上程式碼吧。

程式碼:

#include<iostream>
#include<cstdio>
#include<ctype.h>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
typedef pair<int,int> pairs;
priority_queue<pairs,vector<pairs>,greater<pairs> > q;
inline int read(){
	int x=0,f=0;char ch=getchar();
	while(!isdigit(ch))f|=ch=='-',ch=getchar();
	while(isdigit(ch))x=x*10+(ch^48),ch=getchar();
	return f?-x:x;
}
int head[220007],cnt;
bool vis[220007];
int dis[220007];
int n,m,k,s=1,ans=99999999;
struct Edge{
	int next,to,w;
}edge[40000007];
inline void add_edge(int from,int to,int w){
	edge[++cnt].next=head[from];edge[cnt].w=w;
	edge[cnt].to=to;head[from]=cnt;
}
inline void dijkstra(){
	memset(dis,0x3f,sizeof dis);
	dis[s]=0;q.push(make_pair(dis[s],s));
	while(!q.empty()){
		int x=q.top().second;q.pop();
		if(vis[x])continue;vis[x]=1;
		for(int i=head[x];i;i=edge[i].next){
			int to=edge[i].to;
			if(dis[to]>dis[x]+edge[i].w){
				dis[to]=dis[x]+edge[i].w;
				q.push(make_pair(dis[to],to));
			}
		}
	}
}
int main(){
	n=read(),m=read(),k=read();
	for(int i=1;i<=m;++i){
		int u=read(),v=read(),w=read();
		add_edge(u,v+n,0),add_edge(v,u+n,0);
		for(int j=0;j<k;++j)add_edge(u+j*n,v+j*n+n,0),add_edge(v+j*n,u+j*n+n,0);
		for(int j=0;j<=k;++j){
			add_edge(u+j*n,v+j*n,w);
			add_edge(v+j*n,u+j*n,w);
		}
	}
	dijkstra();
	for(int i=1;i<=k+1;++i)ans=min(ans,dis[i*n]);
	printf("%d",ans);
	return 0;
}