登 录
所谓最小斯泰纳树,很裸,直接套版
/* * File: HNU 10862 Ticket to Ride * Author: xiaotian @ hnu * Created on 2010年10月6日, 下午7:48 * 题解:最小斯泰纳树,直接套板 */ #include<stdio.h> #include<iostream> #include<string> #include<queue> #include<map> #include<set> #include<math.h> using namespace std; #define N 1000 #define A 8 #define inf 0x7ffffff int vis[N], id[A]; //id[]: A中点的标号 int d[N][N], dp[1 << A][N]; //dp[i][v]: 点v到点集i的最短距离 map<string, int>mp, fg; int min(int a, int b) { return a < b ? a : b; } void steiner(int n, int a) { int i, j, k, mx, mk, top = (1 << a); for (k = 0; k < n; k++) for (i = 0; i < n; i++) for (j = 0; j < n; j++) if (d[i][j] > d[i][k] + d[k][j]) d[i][j] = d[i][k] + d[k][j]; for (i = 0; i < a; i++) { // vertex: 0 ~ n-1 for (j = 0; j < n; j++) dp[1 << i][j] = d[j][ id[i] ]; } for (i = 1; i < top; i++) { if (0 == (i & (i - 1))) continue; memset(vis, 0, sizeof (vis)); for (k = 0; k < n; k++) { // init for (dp[i][k] = inf, j = 1; j < i; j++) if ((i | j) == i && dp[i][k] > dp[j][k] + dp[i - j][k]) dp[i][k] = dp[j][k] + dp[i - j][k]; } for (j = 0; mx = inf, j < n; j++) { // update for (k = 0; k < n; k++) if (dp[i][k] <= mx && 0 == vis[k]) mx = dp[i][mk = k]; for (k = 0, vis[mk] = 1; k < n; k++) if (dp[i][mk] > dp[i][k] + d[k][mk]) dp[i][mk] = dp[i][k] + d[k][mk]; } } } int main() { int n, m, a = 8, w; char s1[25], s2[25]; while (scanf("%d%d/n", &n, &m) != EOF) { if (n == 0 && m == 0) return 0; mp.clear(); for (int i = 0; i < n; i++) { scanf("%s",s1); mp[s1] = i + 1; } for (int i = 0; i <= n; i++) for (int j = 0; j <= n; j++) d[i][j] = i==j?0:inf; for (int i = 0; i < m; i++) { scanf("%s %s %d", s1, s2, &w); //printf("%s %s %d/n",s1,s2,w); int u = mp[s1] - 1; int v = mp[s2] - 1; //printf("%d %d/n", u, v); d[u][v] = d[v][u] = min(d[u][v], w); } fg.clear(); for (int i = 0; i < 8; i++) { scanf("%s", s1); id[i] = mp[s1] - 1; //printf("%d/n", id[i]); } steiner(n, a); // enum to find the result int i, j, z, x, y, k, b; for (i = 0, b = inf; z = 0, i < 256; b > z ? b = z : b, i++) for (j = 0; y = 0, j < 4; z += !!y * dp[y][x], j++) for (k = 0; k < 8; k += 2) if ((i >> k & 3) == j) y += 3 << k, x = id[k]; printf("%d/n",b); // TODO: cout << b << endl; } }
抱歉!评论已关闭.