USACO cowtour Floyd + 枚举

给出来的数据量还是可以的。题意:有若干个牧场,至少有两个不连通,一个牧场的直径就是牧场中最远的两个牧区的距离。要求找出几个牧场中最短的直径,就是找一条路径连接几个牧区,使这个直径最终最小。

基本方法,把整个图根据输入划分成几个不连通的牧区,然后求出每个牧区的直径(即每个连通块中的最长路径),然后枚举两个不在同一牧区的点,设blocks[i]记录第i个节点所在连通块的直径,那么result = min(blocks[i] + dis(i, j) + blocks[j]),可以用并查级判断两个点是否连通

/*
ID:kevin_s1
PROG:cowtour
LANG:C++
*/

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <list>
#include <cmath>

using namespace std;

#define MAXN 175
const double INF = 1E15;

//gobal variable====
int N;

struct point{
	double x;
	double y;
}points[MAXN];

double Graph[MAXN][MAXN];

double result;

int Father[MAXN];
int Rank[MAXN];

double blocks[MAXN];
//==================

//function==========

int Find(int x){
	while(x != Father[x]){
		x = Father[x];
	}
	return x;
}

bool check(int x, int y){
	x = Find(x);
	y = Find(y);
	if(x == y)
		return true;
	else
		return false;
}

void Union(int x, int y){
	x = Find(x);
	y = Find(y);
	if(x == y)
		return;
	if(Rank[x] >= Rank[y]){
		Father[y] = x;
		Rank[x] += Rank[y];
	}
	else{
		Father[x] = y;
		Rank[y] += Rank[x];
	}
}

double dist(point start, point end){
	return sqrt((end.x - start.x)*(end.x - start.x) + (end.y - start.y)*(end.y - start.y));
}

void Input(){
	cin>>N;
	for(int i = 1; i <= N; i++){
		cin>>points[i].x>>points[i].y;
		blocks[i] = -1;
		Father[i] = i;
		Rank[i] = 1;
	}
	char flg;
	for(int i = 1; i <= N; i++)
		for(int j = 1; j <= N; j++){
			cin>>flg;
			if(i == j)
				Graph[i][j] = 0;
			else if(flg == '1'){
				Union(i, j);
				Graph[i][j] = dist(points[i], points[j]);
			}
			else if(flg == '0')
				Graph[i][j] = INF;
		}
}

void Floyd(){
	for(int k = 1; k <= N; k++){
		for(int i = 1; i <= N; i++){
			for(int j = 1; j <= N; j++){
				if(k == i || k == j)
					continue;
				if(Graph[i][j] > Graph[i][k] + Graph[k][j]){
					Graph[i][j] = Graph[i][k] + Graph[k][j];
				}
			}
		}
	}
}

void print(){
	for(int i = 1; i <= N; i++){
		for(int j = 1; j <= N; j++){
			cout<<Graph[i][j]<<" ";
		}
		cout<<endl;
	}
}

//==================

int main(){
	freopen("cowtour.in","r",stdin);
	freopen("cowtour.out","w",stdout);
	Input();
	Floyd();
	for(int i = 1; i <= N; i++){
		for(int j = 1; j <= N; j++){
			if(Graph[i][j] != INF && blocks[i] < Graph[j][i])
				blocks[i] = Graph[j][i];
		}
	}

	result = INF;
	for(int i = 1; i <= N; i++){
		for(int j = i + 1; j <= N; j++){
			if(Graph[i][j] == INF && !check(i, j)){
				double dis = dist(points[i], points[j]);
				if(blocks[i] + dis + blocks[j] < result)
					result = blocks[i] + dis + blocks[j];
			}
		}
	}

	for(int i = 1; i <= N; i++)
		if(blocks[i] > result)
			result = blocks[i];

	printf("%.6lf\n", result);
	return 0;
}

USACO cowtour Floyd + 枚举

时间: 2024-11-10 04:41:06

USACO cowtour Floyd + 枚举的相关文章

poj1178 floyd+枚举

http://poj.org/problem?id=1178 Description Centuries ago, King Arthur and the Knights of the Round Table used to meet every year on New Year's Day to celebrate their fellowship. In remembrance of these events, we consider a board game for one player,

【基础练习】【floyd+枚举】codevs1020 孪生蜘蛛题解

题目描述 Description 在G城保卫战中,超级孪生蜘蛛Phantom001和Phantom002作为第三层防卫被派往守护内城南端一带极为隐秘的通道. 根据防护中心的消息,敌方已经有一只特种飞蛾避过第二层防卫,直逼内城南端通道入口.但优秀的蜘蛛已经在每个通道内埋下了坚固的大网,无论飞蛾进入哪个通道,他只有死路一条!(因为他是无法挣脱超级蛛网的) 现在,001和002分别驻扎在某两个通道内.各通道通过内线相通,通过每条内线需要一定的时间.当特种飞蛾被困某处,001或002会迅速赶来把它结果掉

Stockbroker Grapevine (poj 1125 floyd + 枚举)

Language: Default Stockbroker Grapevine Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 27445   Accepted: 15211 Description Stockbrokers are known to overreact to rumours. You have been contracted to develop a method of spreading disinfo

poj 1161 Floyd+枚举

题意是: 给出n个点,围成m个区域.从区域到另一个区域间需穿过至少一条边(若两区域相邻)——边连接着两点. 给出这么一幅图,并给出一些点,问从这些点到同一个区域的穿过边数最小值. 解题思路如下: 将区域按1~m编号,d[i][j]表示第 i 个区域到第 j 个区域的最短距离,跑一遍Floye算法O(m^3)后,枚举选择的区域,找出其中穿过边数最小值即可. 建图:题目对于每个区域的描述方式为以顺时针方向给出围成区域的点.由此可知区域由哪些边组成.易知,每条边能且只能令两个区域相邻,则用二维数组记录

USACO ariprog 暴力枚举+剪枝

/* ID:kevin_s1 PROG:ariprog LANG:C++ */ #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <vector> #include <map> #include <set> #include <algorithm> #include <cstdlib>

IOI 2000 Walls Floyd+枚举

Walls   PROBLEM In a country, great walls have been built in such a way that every great wall connects exactly two towns. The great walls do not cross each other. Thus, the country is divided into such regions that to move from one region to another,

bzoj 1491: [NOI2007]社交网络

Description 在社交网络(socialnetwork)的研究中,我们常常使用图论概念去解释一些社会现象.不妨看这样的一个问题. 在一个社交圈子里有n个人,人与人之间有不同程度的关系.我们将这个关系网络对应到一个n个结点的无向图上, 两个不同的人若互相认识,则在他们对应的结点之间连接一条无向边,并附上一个正数权值c,c越小,表示两个人 之间的关系越密切.我们可以用对应结点之间的最短路长度来衡量两个人s和t之间的关系密切程度,注意到最短路 径上的其他结点为s和t的联系提供了某种便利,即这些

[bzoj2208][Jsoi2010]连通数

来自FallDream的博客,未经允许,请勿转载,谢谢. n<=2000 bitset优化floyd , 枚举k,枚举i,如果i能到k,那么i的bitset直接或上k的.复杂度$O(\frac{n^{3}}{32})$ #include<iostream> #include<cstdio> #include<bitset> #define MN 2000 using namespace std; inline int read() { int x = 0 , f

CodeVS 1020孪生蜘蛛

虽然最近最短路写的挺熟练的,但这道题还是坑了我两个小时..   题目大意:在一个无向图里找两个结点使在除了这两个结点以外的任意一个结点到这两个结点的权值最小.(距离为出发结点到两     个结点的最小权值).   算法:Floyd+枚举(SPFA蜜汁TLE..)      首先这道题读了好几遍都不知道它要求什么(题意好迷啊..),一直不明白什么叫最坏情况下的最优解,按自己的理解打了spfa,交    上去全wa..于是按着wa的数据手动画了个图,然后跟着答案去推,才发现是求一波最短路再枚举两个点