1926 - 城墙
时间限制 : 1 秒
内存限制 : 128 MB
有一个国家,城市之间都用城墙连接起来,每个城市里有一个或者没有打高尔夫的高手。现在这些高尔夫高手打算挑一个空地r一决高下(空地就是由城墙围起来的地方)。由于国家管制,所属i城市的人不能去其他任意的城市。因此有些人要去空地r不得不翻越一些城墙,当然翻墙是件很困难的事情,所以尽量能少翻墙。现在问你挑哪个区域来做为他们比赛的地点,使得他们翻过墙的总和最小。

Figure1:输入样例情况图
Figure2:翻越城墙数最小的一种情况
题目输入
第一行:M 表示空地数(2 <= M <= 200)
第二行:N 表示城市数目(3 <= N <= 250)
第三行:L 表示高尔夫高手人数(1 <= L <= 30)
第四行:L个数字,依次表示L位高尔夫高手所在城市编号
接下来2*M行:每两行对应一个空地,第一行表示空地周围的城市数,第二行表示城市的代号,前M-1个按城市编号按顺时针顺序输出,第M个按逆时针输出。
题目输出
输出一个整数:总共需要翻越的城墙数的最小值
输入/输出样例
输入格式
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
C++解答
/*其实这个题就是把点当成面来给了,对于某一个区域,把他当成一个点, 和他相邻的区域与他之间有一条权为1的边, */ #include<stdio.h> #include<string.h> #define Max 210 #define INF 10000000 #define M 210 #define N 260 bool map[M][M]; struct Area { int town; //在该区域边上城镇数 int turn[N]; //这些城镇依次是turn[n]; int f[N]; //f[i]记i是turn[n]的第f[i]个数 }area[M]; bool check(int x, int y) { int i, a, b, t; bool yes = 0; for(i = 0; i < area[y].town; i++){ a = area[y].turn[i]; b = area[y].turn[(i+1)%area[y].town]; if(area[x].f[a] != -1 && area[x].f[b] != -1) { t = area[x].f[a]-area[x].f[b]; if(t == -1 || t == 1 || t == area[x].town-1 || t == 1-area[x].town) { yes = 1; break; } } } return yes; } int A[Max][Max]; void Floyd(int n) { int i, j, k; for(i = 0; i < n; i++){ for(j = 0; j < n; j++){ if(i != j && !map[i][j]) A[i][j] = INF; else A[i][j] = map[i][j]; } } for(k = 0; k < n; k++){ for(i = 0; i < n; i++) for(j = 0; j < n; j++) if(A[i][j] > A[i][k]+A[k][j]) A[i][j] = A[i][k]+A[k][j]; } } int main() { int i, j, m, n, l, man[40]; int town[N][N], num[N]; //freopen("walls.in", "r", stdin); //freopen("walls.out", "w", stdout); scanf("%d", &m); scanf("%d", &n); scanf("%d", &l); for(i = 0; i < l; i++) scanf("%d", &man[i]); memset(map, 0, sizeof(map)); memset(num, 0, sizeof(num)); for(i = 0; i < m; i++){ scanf("%d", &area[i].town); memset(area[i].f, -1, sizeof(area[i].f)); for(j = 0; j < area[i].town; j++){ scanf("%d", &area[i].turn[j]); area[i].f[area[i].turn[j]] = j; town[area[i].turn[j]][num[area[i].turn[j]]] = i; num[area[i].turn[j]]++; } for(j = 0; j < i; j++) map[i][j] = map[j][i] = check(i, j); } Floyd(m); int minsum, sum, min, k; for(i = 0; i < m; i++){ sum = 0; for(j = 0; j < l; j++){ min = A[town[man[j]][0]][i]; for(k = 1; k < num[man[j]]; k++){ if(min > A[town[man[j]][k]][i]) min = A[town[man[j]][k]][i]; } sum += min; } if(!i) minsum = sum; else if(minsum > sum) minsum = sum; } printf("%d\n", minsum); // } return 0; }