[HAOI2005] 希望小学

  首先我想说这道题用floyed是一定不能得出正确的代价的,但是这道题并不需要求出代价,我也不知道为什么floyed总能得出正确的建立学校的村庄,这题只有5组数据,我想反例一定存在,不过我不想想。

  我认为正确的解法是对每个点跑一遍dijstra。很多人是直接建图预处理出每一条边的权,之后跑一边floyed,但是这个边权只能代表两个有道路直接相连的村庄来往的正确代价,比如说村1和村2有道路a,村2和村3有道路b,预处理后权w[a]=x,w[b]=y,但是村1的孩子去村3上学花费的时间不是w[a]+w[b],这是很显然的,边权是与走这条边的人数直接相关的,所以应该用dijstra递推才能得出真正正确的结果,如果这道题目要求输出代价会卡掉很多很多份代码,因为大家都是floyed跑的,我也是......我第一思路也是floyed,后来发现好像不太对,但是我也不想改了。

 

// q.c

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int M=100,INF=(int)1e8;
int N,B,B1,B2,B3,G1,G2,G3,K,sumB,sumG,x[M+10],y[M+10],w[M+10][M+10];
int ans1=INF,ans2;
int main() {
	freopen("hopeschool.in","r",stdin);
	freopen("hopeschool.out","w",stdout);
	scanf("%d%d%d%d%d%d%d",&N,&B1,&B2,&B3,&G1,&G2,&G3);
	for(int i=1;i<=N;i++) scanf("%d",&x[i]),sumB+=x[i];
	for(int i=1;i<=N;i++) scanf("%d",&y[i]),sumG+=y[i];
	scanf("%d",&K);
	int a,b,c,d,e;
	for(int i=1;i<=K;i++) {
		scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
		w[a][b]+=(sumB-x[b])*(B1*c+B2*d+B3*e);
		w[a][b]+=(sumG-y[b])*(G1*c+G2*d+G3*e);
		w[b][a]+=(sumB-x[a])*(B1*c+B2*e+B3*d);
		w[b][a]+=(sumG-y[a])*(G1*c+G2*e+G3*d);
	}
	for(int i=1;i<=N;i++)
		for(int j=1;j<=N;j++)
			if(i!=j&&!w[i][j]) w[i][j]=INF;
	for(int k=1;k<=N;k++)
		for(int i=1;i<=N;i++)
			for(int j=1;j<=N;j++)
				if(k!=i&&i!=j&&k!=j)
					w[i][j]=min(w[i][j],w[i][k]+w[k][j]);
	for(int i=1;i<=N;i++) {
		int sum=0;
		for(int j=1;j<=N;j++) if(w[j][i]!=INF) sum+=w[j][i];
		if(sum<ans1) ans1=sum,ans2=i;
	}
	printf("%d\n",ans2);
	return 0;
}

 

posted @ 2018-03-29 21:47  qjs12  阅读(115)  评论(0编辑  收藏  举报