描述
在一个国家,长城的建造方式使每一堵长城都把两个城镇连在一起。长城不相交。因此,国家被划分为这样的地区:要从一个地区迁移到另一个地区,就必须穿过一个城镇或跨过长城。对于任何两个城镇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;
}