P3094 [USACO13DEC]假期计划Vacation Planning

题目描述

有N(1 <= N <=
200)个农场,用1…N编号。航空公司计划在农场间建立航线。对于任意一条航线,选择农场1…K中的农场作为枢纽(1 <= K <=
100, K <= N)。

当前共有M (1 <= M <= 10,000)条单向航线连接这些农场,从农场u_i 到农场 v_i, 将花费 d_i美元。(1 <=
d_i <= 1,000,000).

航空公司最近收到Q (1 <= Q <= 10,000)个单向航行请求。第i个航行请求是从农场a_i到农场
b_i,航行必须经过至少一个枢纽农场(可以是起点或者终点农场),因此可能会多次经过某些农场。

请计算可行航行请求的数量,及完成所有可行请求的总费用

输入格式

  • Line 1: Four integers: N, M, K, and Q.

  • Lines 2…1+M: Line i+1 contains u_i, v_i, and d_i for flight i.

  • Lines 2+M…1+M+Q: Line 1+M+i describes the ith trip in terms of a_i and b_i

输出格式

  • Line 1: The number of trips (out of Q) for which a valid route is possible.

  • Line 2: The sum, over all trips for which a valid route is possible, of the minimum possible route cost.

输入输出样例
输入 #1

3 3 1 3 3 1 10 1 3 10 1 2 7 3 2 2 3 1 2

输出 #1

2 24

说明/提示

There are three farms (numbered 1…3); farm 1 is a hub. There is a $10
flight from farm 3 to farm 1, and so on. We wish to look for trips
from farm 3 to farm 2, from 2->3, and from 1->2.

The trip from 3->2 has only one possible route, of cost 10+7. The trip
from 2->3 has no valid route, since there is no flight leaving farm 2.
The trip from 1->2 has only one valid route again, of cost 7.

这个题写在这里提醒自己不要轻视普及组的题。不要以为一个弗洛伊德就够了。这个得两个。。。。。。。。。。。。。

#include<bits/stdc++.h>
using namespace std;
const int maxn=210;
long long dp[2100][2100],w[2100][2100],dp1[maxn][maxn];
bool vis[maxn][maxn];
long long ans=0,sum=0;
int main() {
	memset(w,63,sizeof(w));
	memset(dp,63,sizeof(dp));
	memset(dp1,63,sizeof(dp1));
	int n,m,k,q;
	cin>>n>>m>>k>>q;
	while(m--) {
		long long x,y,z;
		cin>>x>>y>>z;
		dp[x][y]=min(dp[x][y],z);
		if(x<=k||y<=k)dp1[x][y]=min(dp1[x][y],z);
	}
	for(int r=1; r<=n; r++)
		for(int i=1; i<=n; i++)
			for(int j=1; j<=n; j++) {
				dp[i][j]=min(dp[i][r]+dp[r][j],dp[i][j]);
			}
	for(int r=1; r<=n; r++)//起点 
		for(int i=1; i<=k; i++)
			for(int j=1; j<=n; j++) {
				dp1[i][j]=min(dp[i][r]+dp[r][j],dp1[i][j]);
			}
	for(int r=1; r<=n; r++)//终点 
		for(int i=1; i<=n; i++)
			for(int j=1; j<=k; j++) {
				dp1[i][j]=min(dp[i][r]+dp[r][j],dp1[i][j]);
			}
	for(int r=1; r<=k; r++)//中点 
		for(int i=1; i<=n; i++)
			for(int j=1; j<=n; j++) {
				dp1[i][j]=min(dp[i][r]+dp[r][j],dp1[i][j]);
			}

	while(q--) {
		int x,y;
		cin>>x>>y;
		if(dp1[x][y]!=dp[0][0]) {
			ans++;
			sum+=dp1[x][y];
		}
	}
	cout<<ans<<endl<<sum<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值