Ticket to Ride
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 805 | Accepted: 366 |
Description
Ticket to Ride is a board game for up to 5 players. The goal of the game is to set up train lines (and to thwart the opponents' attempts at setting up their train lines). At the beginning of play, each player is assigned four train lines. A player may choose to discard as many of these four assignments as she likes. Each assignment has a score, corresponding to its difficulty (so, typically, a train line between e.g. Stockholm and Tokyo would be worth more than a train line between e.g. Stockholm and Utrecht). At the end of the game, each player gets points for the assignments that they have successfully completed, and penalty points for the assignments that they have failed to complete.
An assignment consists of a pair of cities that are to be connected by a series of shorter railway routes. A route can be claimed (for a certain cost associated with the route), but things are complicated by the fact that there is only a limited number of routes, and once a player claims a route, none of the other players can claim it. A player has successfully set up a train line between two cities if there is a path between the two cities using only routes that have been claimed by this player. For simplicity, we will ignore all additional aspects of the game (including the actual process of claiming routes and additional ways to score points).
For instance, if your assignment is to connect Stockholm and Amsterdam in the Figure above, you would probably want to claim the routes between Stockholm and Copenhagen, and between Copenhagen and Amsterdam. But if another player manages to claim the route between Copenhagen and Stockholm before you, your train line would have to use some other routes, e.g. by going to Copenhagen via Oslo.
In this problem, we will consider the rather bold strategy of trying to complete all four assignments (typically, this will be quite hard). As a preliminary assessment of the difficulty of achieving this, we would like to calculate the minimum cost of setting up all four lines assuming that none of the other players interfere with our plans. Your job is to write a program to determine this minimum cost.
An assignment consists of a pair of cities that are to be connected by a series of shorter railway routes. A route can be claimed (for a certain cost associated with the route), but things are complicated by the fact that there is only a limited number of routes, and once a player claims a route, none of the other players can claim it. A player has successfully set up a train line between two cities if there is a path between the two cities using only routes that have been claimed by this player. For simplicity, we will ignore all additional aspects of the game (including the actual process of claiming routes and additional ways to score points).
For instance, if your assignment is to connect Stockholm and Amsterdam in the Figure above, you would probably want to claim the routes between Stockholm and Copenhagen, and between Copenhagen and Amsterdam. But if another player manages to claim the route between Copenhagen and Stockholm before you, your train line would have to use some other routes, e.g. by going to Copenhagen via Oslo.
In this problem, we will consider the rather bold strategy of trying to complete all four assignments (typically, this will be quite hard). As a preliminary assessment of the difficulty of achieving this, we would like to calculate the minimum cost of setting up all four lines assuming that none of the other players interfere with our plans. Your job is to write a program to determine this minimum cost.
Input
The input consists of several (at most 20) games to be analyzed. Each game starts with two integers 1 ≤ n ≤ 30, 0 ≤ m ≤ 1 000, giving the number of cities and railway routes in the map, respectively. Then follow n lines, giving the names of the n cities. City names are at most 20 characters long and consist solely of lower case letters ('a'-'z').
After this follow m lines, each containing the names of two different cities and an integer 1 ≤ c ≤ 10 000, indicating that there is a railway route with cost c between the two cities. Note that there may be several railway routes between the same pair of cities. You may assume that it is always possible to set up a train line from any city to any other city. Finally, there will be four lines, each containing the names of two cities, giving the four train line assignments.
The input is terminated by a case where n = m = 0. This case should not be processed.
After this follow m lines, each containing the names of two different cities and an integer 1 ≤ c ≤ 10 000, indicating that there is a railway route with cost c between the two cities. Note that there may be several railway routes between the same pair of cities. You may assume that it is always possible to set up a train line from any city to any other city. Finally, there will be four lines, each containing the names of two cities, giving the four train line assignments.
The input is terminated by a case where n = m = 0. This case should not be processed.
Output
For each game, output a single line containing a single integer, the minimum possible cost to set up all four train lines.
Sample Input
10 15 stockholm amsterdam london berlin copenhagen oslo helsinki dublin reykjavik brussels oslo stockholm 415 stockholm helsinki 396 oslo london 1153 oslo copenhagen 485 stockholm copenhagen 522 copenhagen berlin 354 copenhagen amsterdam 622 helsinki berlin 1107 london amsterdam 356 berlin amsterdam 575 london dublin 463 reykjavik dublin 1498 reykjavik oslo 1748 london brussels 318 brussels amsterdam 173 stockholm amsterdam oslo london reykjavik dublin brussels helsinki 2 1 first second first second 10 first first first first second first first first 0 0
Sample Output
3907 10
Source
题意:给出一个无向图,和四对数据。每对数据分别为图中的两个点。要求添加一些边,使每对点都能连通,让总边权最小
解题思路:斯坦纳树
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;
int n, m, cnt, u, v, w;
int status;//表示0~n号节点都被选择时的状态+1
int s[40], nt[2009], e[2009], val[2009];
int dis[40][1000], vis[40], ans[1000], flag[1000];
//dis[i][j]表示以i节点为根选择点集状态为j时的最小值;vis[i][j]表示i节点为点集j时是否在队列中
queue<int>q;
map<string, int>mp;
char s1[30], s2[30];
void init()
{
memset(vis, 0, sizeof vis);
memset(s, -1, sizeof s);
mp.clear();
cnt = 0;
status = 1 << 8;
for (int i = 1; i <= n; i++)
for (int j = 0; j < status; j++)
dis[i][j] = INF;
}
void SPFA(int sta)
{
while (!q.empty())
{
int pre = q.front();
q.pop();
vis[pre] = 0;
for (int i = s[pre]; ~i; i = nt[i])
{
if (dis[pre][sta] + val[i] < dis[e[i]][sta])
{
dis[e[i]][sta] = dis[pre][sta] + val[i];
if (!vis[e[i]])
{
vis[e[i]] = 1;
q.push(e[i]);
}
}
}
}
}
void Steiner_Tree()
{
for (int i = 0; i < status; i++)
{
for (int j = 1; j <= n; j++)
{
for (int k = i; k; k = (k - 1) & i)
dis[j][i] = min(dis[j][i], dis[j][k] + dis[j][i - k]);
if (dis[j][i] != INF)
{
q.push(j);
vis[j] = 1;
}
}
SPFA(i);
}
}
int check(int k)
{
for (int i = 0; i < 4; i++)
if ((k >> i & 1) ^ (k >> (i + 4) & 1)) return 0;
return 1;
}
int main()
{
while (~scanf("%d %d", &n, &m) && (n + m))
{
init();
for (int i = 1; i <= n; i++) scanf("%s", s1), mp[s1] = i;
for (int i = 1; i <= m; i++)
{
scanf("%s%s%d", s1, s2, &w);
u = mp[s1], v = mp[s2];
nt[cnt] = s[u], s[u] = cnt, e[cnt] = v, val[cnt++] = w;
nt[cnt] = s[v], s[v] = cnt, e[cnt] = u, val[cnt++] = w;
}
for (int i = 1; i <= 8; i++)
{
scanf("%s", s1);
int temp = ((i & 1) ? i / 2 : i / 2 + 3);
dis[mp[s1]][1 << temp] = 0;
}
Steiner_Tree();
for (int i = 0; i < status; i++)
{
flag[i] = check(i), ans[i] = INF;
for (int j = 1; j <= n; j++) ans[i] = min(ans[i], dis[j][i]);
}
for (int i = 0; i < status; i++)
if (flag[i])
{
for (int j = i; j; j = (j - 1)&i)
if (flag[j] && flag[i - j]) ans[i] = min(ans[i], ans[j] + ans[i - j]);
}
printf("%d\n", ans[status - 1]);
}
return 0;
}