P2966 [USACO09DEC] Cow Toll Paths G

copy来的题面

给定一个 nnmm 边的双向图,第 ii 条道路连接了 uiu_iviv_i,边权为 wiw_i,第 ii 个点的点权为 cic_i

给定 qq 组询问,第 ii 组询问求从 sis_itit_i 的路径的边权之和与点权的最大值的和的最小值。

可能有重边,但保证无自环。

对于 100%100\% 的数据,1n2501 \le n \le 2501m1041 \le m \le 10^41q1041 \le q \le 10^4

分析

一看1n2501 \le n \le 250,就知道是flyd,但本题的题面实在有点绕,英译中再译中一下,就是输出两点之间的最短路长度加上该条最短路径上的最大点权的最小值

分别以pos[i].idpos[i].w记录点ii的编号和点权,从小到大排序。

处理时就先跑常规的最短路

int u=pos[i].id,v=pos[j].id,kk=pos[k].id;
flyd[u][v]=min(flyd[u][v],flyd[u][kk]+flyd[kk][v]);

由于已经排过序了,所以这里得转一下用pos[i].idpos[j].idpos[k].id表示点。

最大点权比较时,注意不能只算kk这一个,因为kk只是中转点,所以i,ji,j也得算上。

代码部分

#include<bits/stdc++.h>
using namespace std;
const int maxn=552;
int n,m,q;
int flyd[maxn][maxn];
struct node {
	int id,w;
} pos[maxn];
bool cmp(node x,node y) {
	return x.w<y.w;
}
int ans[maxn][maxn];
int main() {
	memset(ans,0x3f,sizeof(ans));
	cin>>n>>m>>q;
	for(int i=1; i<=n; i++) {
		cin>>pos[i].w;
		pos[i].id=i;
	}
	sort(pos+1,pos+1+n,cmp);
	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++) {
			if(i!=j)
				flyd[i][j]=0x3f3f3f3f;
			else
				flyd[i][j]=0;
		}
	for(int i=1; i<=m; i++) {
		int u,v,w;
		cin>>u>>v>>w;
		flyd[u][v]=min(flyd[u][v],w);
		flyd[v][u]=min(flyd[v][u],w);
	}
	for(int k=1; k<=n; k++) {
		for(int i=1; i<=n; i++) {
			for(int j=1; j<=n; j++) {
				int u=pos[i].id,v=pos[j].id,kk=pos[k].id;
				flyd[u][v]=min(flyd[u][v],flyd[u][kk]+flyd[kk][v]);
				ans[u][v]=min(ans[u][v],flyd[u][v]+max(pos[i].w,max(pos[j].w,pos[k].w)));
			}
		}
	}
	while(q--) {
		int u,v;
		cin>>u>>v;
		cout<<ans[u][v]<<endl;
	}
	return 0;
}
posted @ 2023-11-04 21:30  p7gab  阅读(0)  评论(0编辑  收藏  举报  来源