poj—1161 -- Walls

描述

在一个国家,长城的建造方式使每一堵长城都把两个城镇连在一起。长城不相交。因此,国家被划分为这样的地区:要从一个地区迁移到另一个地区,就必须穿过一个城镇或跨过长城。对于任何两个城镇A和B,最多有一个长城,一端在A,另一个在B,而且,它可以走从A到B总是走在一个城镇或沿着长城。输入格式意味着附加限制。

有一个俱乐部的成员住在城镇。每个城镇只有一个成员,或者根本没有成员。成员们想在其中一个地区(任何城镇之外)开会。成员们骑着自行车旅行。他们不想进入任何城镇,因为交通,他们想跨越尽可能少的长城,因为这是一个很大的麻烦。要进入会议区域,每个成员都需要跨越一个数(可能是0)的长城。他们希望找到这样一个最优区域,使这些数字的和(简称交叉和)最小。


城镇用从1到N的整数标记,其中N是城镇的数目。在图1中,标记的节点代表城镇,连接节点的线代表长城。假设有三个成员,他们住在城镇3,6和9。然后,图2显示了成员的最佳会议区域和各自的路径。交叉金额为2:来自9镇的成员必须在2和4镇之间穿越长城,而来自6镇的成员必须在4和7镇之间横渡。

您将编写一个程序,给定城镇、地区和俱乐部成员家乡城镇,计算最佳区域和最小交叉和。

输入

您的程序是从标准输入读取。第一行包含一个整数:区域数M,2<=M<=200。第二行包含一个整数:城镇数N,3<=N<=250。第三行包含一个整数:俱乐部成员数L,1<=L<=30,L<=N。第四行包含L个不同整数,按递增顺序排列:成员所在城镇的标签。

在此之后,输入包含2M行,因此每个区域都有一对线:2m线的前两行描述第一个区域,接下来的两个描述第二个区域,以此类推。在这两个人中,第一行显示了该地区边界上的城镇数量。该对的第二行包含i整数:这些i城镇的标签按某种顺序排列,在沿区域边界顺时针方向旅行时,它们可以传递,但有以下例外。最后一个区域是围绕所有城镇和其他地区的“外部区域”,因此标签的顺序对应于逆时针方向的行程。区域的顺序给出了区域的整数标号:第一个区域有标号1,第二个区域有标号2,等等。请注意,输入包括城镇和长城形成的所有区域,包括“外部区域”。

输出量

你的程序是写到标准输出。第一行包含一个整数:最小交叉和。

样本输入

10
10
3
3 6 9 
3
1 2 3 
3
1 3 7 
4
2 4 7 3 
3
4 6 7 
3
4 8 6 
3
6 8 7 
3
4 5 8 
4
7 8 10 9 
3
5 10 8 
7
7 9 10 5 4 2 1

样本输出

2

题解:将每一个区域看成点,若 i 区域与 j 区域相连则令mp[i][j]=1,再把图建好后,进行进行floyd算法求出区域间的最短路,最后枚举每一个区域得出最小值。

ac code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
using namespace std;
#define N 305
#define inf 10000
int m,l,n;
struct e {
	int v;
	set<int>s;
};
e me[N];
set<pair<int, int> >q[N];
int mes[N], ts[N];
int mp[N][N], mx = inf;
int main() {
	int nu, p;
	memset(mp, inf, sizeof(mp));
	cin >> m >> n >> l;
	for (int i = 0; i < n; i++)
		me[i].v = 0;
	for (int i = 0; i < l; i++) {
		cin >> ts[i];
		me[ts[i]].v = 1;
	}
	int t = 0;
	for (int i = 0; i < m; i++) {
		scanf("%d", &nu);
		for (int j = 0; j < nu; j++) {
			scanf("%d", &mes[j]);
			if (me[mes[j]].v) {
				me[mes[j]].s.insert(i);
			}
			if (j > 0) {
				if (j == nu - 1) {
					q[i].insert(make_pair(mes[j], mes[0]));
					q[i].insert(make_pair(mes[0], mes[j]));
				}
				q[i].insert(make_pair(mes[j], mes[j - 1]));
				q[i].insert(make_pair(mes[j - 1], mes[j]));
			}
		}
	}
	//cout << "Y" << endl;
	for (int i = 0; i < n; i++)
		mp[i][i] = 0;
	for (int i = 0; i < m; i++) {
		for (int j = i + 1; j < m; j++) {
			for (set<pair<int,int> >::iterator ite = q[j].begin(); ite != q[j].end(); ite++) {
				if (q[i].count(*ite)) {
					//cout << ite->first << " " << ite->second << endl;
					mp[i][j] = 1;
					mp[j][i] = 1;
					break;
				}
			}
		}
	}
	for (int k = 0; k < m; k++) {
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < m; j++) {
				if (mp[i][j] > mp[i][k] + mp[k][j]) {
					mp[i][j] = mp[i][k] + mp[k][j];
				}
			}
		}
	}
	int sum = 0, sums =100000;
	for (int i = 0; i < m; i++) {
		sum = 0;
		for (int j = 0; j < l; j++) {
			mx = inf;
			for (set<int>::iterator ier = me[ts[j]].s.begin(); ier != me[ts[j]].s.end(); ier++) {
				//cout << i << " " << ts[j] << " " << *ier << " " << mp[i][*ier] << endl;
				mx = min(mx, mp[i][*ier]);
			}
			sum += (mx);
		}
		sums = min(sums, sum);
	}
	cout << sums << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/usernamezzz/article/details/84865810