Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 1824 | Accepted: 683 |
Description
World Wide Networks (WWN) is a leading company that operates large telecommunication networks. WWN would like to setup a new network in Borduria, a nice country that recently managed to get rid of its military dictator Kurvi-Tasch and which is now seeking for investments of international companies (for a complete description of Borduria, have a look to the following Tintin albums ``King Ottokar's Sceptre", ``The Calculus Affair" and ``Tintin and the Picaros"). You are requested to help WWN todecide how to setup its network for a minimal total cost.
Problem
There are several local companies running small networks (called subnetworks in the following) that partially cover the n largest cities of Borduria. WWN would like to setup a network that connects all n cities. To achieve this, it can either build edges between cities from scratch or it can buy one or several subnetworks from local companies. You are requested to help WWN to decide how to setup its network for a minimal total cost.
- All n cities are located by their two-dimensional Cartesian coordinates.
- There are q existing subnetworks. If q>=1 then each subnetwork c ( 1<=c<=q ) is defined by a set of interconnected cities (the exact shape of a subnetwork is not relevant to our problem).
- A subnetwork c can be bought for a total cost wc and it cannot be split (i.e., the network cannot be fractioned).
- To connect two cities that are not connected through the subnetworks bought, WWN has to build an edge whose cost is exactly the square of the Euclidean distance between the cities.
You have to decide which existing networks you buy and which edges you setup so that the total cost is minimal. Note that the number of existing networks is always very small (typically smaller than 8).
A 115 Cities Instance
Consider a 115 cities instance of the problem with 4 subnetworks (the 4 first graphs in Figure 1). As mentioned earlier the exact shape of a subnetwork is not relevant still, to keep figures easy to read, we have assumed an arbitrary tree like structure for each subnetworks. The bottom network in Figure 1 corresponds to the solution in which the first and the third networks have been bought. Thin edges correspond to edges build from scratch while thick edges are those from one of the initial networks.
Input
The first line contains the number n of cities in the country ( 1<=n<=1000 ) followed by the number q of existing subnetworks ( 0<=q<=8 ). Cities are identified by a unique integer value ranging from 1 to n . The first line is followed by q lines (one per subnetwork), all of them following the same pattern: The first integer is the number of cities in the subnetwork. The second integer is the the cost of the subnetwork (not greater than 2 x 106 ). The remaining integers on the line (as many as the number of cities in the subnetwork) are the identifiers of the cities in the subnetwork. The last part of the file contains n lines that provide the coordinates of the cities (city 1 on the first line, city 2 on the second one, etc). Each line is made of 2 integer values (ranging from 0 to 3000) corresponding to the integer coordinates of the city.
Output
Your program has to write the optimal total cost to interconnect all cities.
Sample Input
7 3 2 4 1 2 3 3 3 6 7 3 9 2 4 5 0 2 4 0 2 0 4 2 1 3 0 5 4 4
Sample Output
17
Hint
Sample Explanation: The above instance is shown in Figure 2. An optimal solution is described in Figure 3 (thick edges come from an existing network while thin edges have been setup from scratch).
Figure 3: An optimal solution of the 7 City instance in which which the first and second existing networkshave been bought while two extra edges (1, 5) and (2, 4)
Source
Regionals 2005 >> Europe - Southwestern
问题链接:UVA1151 UVALive3505 Buy or Build
问题描述:
第1行输入n和q,n是城市数量(编号为1~n),q是方案数。接下来有q行,每行的第1个数为城市数k,第2个数为用该方案需要的代价cost,后面的k个数为城市的编号。接下来n行为第n个城市所在的坐标位置。
在城市间建设道路,使得相互连通。建设道路的花费是两个城市之间的坐标的欧几里德距离;若买方案,则方案内的城市已经连通。求最小花费。
问题分析:
这是一个最小生成树的为问题,解决的算法有Kruskal(克鲁斯卡尔)算法和Prim(普里姆) 算法。
先求一个最小生成树,再枚举方案求最小生成树,求最小值作为最小花费。
程序说明:
本程序使用Kruskal算法实现。有关最小生成树的问题,使用克鲁斯卡尔算法更具有优势,只需要对所有的边进行排序后处理一遍即可。程序中使用了并查集,用来判定加入一条边后会不会产生循环。程序中,图采用边列表的方式存储,排序一下就好了。
这个题与参考链接的题是同一个题,只是输入输出不同。
参考链接:POJ2784 Buy or Build【Kruskal算法+并查集+枚举】
AC的C++语言程序如下:
/* UVA1151 UVALive3505 Buy or Build */
#include <iostream>
#include <algorithm>
#include <vector>
#include <stdio.h>
using namespace std;
const int N = 1100;
const int Q = 8;
vector<int> g[Q+ 1];
int cost[Q + 1];
int n, q;
int f[N + 1];
void UFInit(int n)
{
for(int i = 1; i <=n; i++)
f[i] = i;
}
int Find(int a) {
return a == f[a] ? a : f[a] = Find(f[a]);
}
bool Union(int a, int b)
{
a = Find(a);
b = Find(b);
if (a != b) {
f[a] = b;
return true;
} else
return false;
}
struct Edge {
int u, v, w;
} e[N * (N - 1)];
struct Point
{
int x, y;
} p[N + 1];
bool cmp(Edge a, Edge b)
{
return a.w < b.w;
}
// 两点之间的欧几里德距离
int caldist(Point& a, Point& b)
{
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
int kruskal(int m)
{
int ans = 0, cnt = 0;
for(int i = 0; i < m; i++) {
if(Union(e[i].u, e[i].v)) {
ans += e[i].w;
if(++cnt == n - 1)
break;
}
}
return ans;
}
int main()
{
int t;
scanf("%d", &t);
while(t--) {
for(int i = 0; i <= Q; i++)
g[i].clear();
scanf("%d%d", &n, &q);
for(int i = 0; i < q; i++) {
int k = 0;
scanf("%d%d", &k, &cost[i]);
for(int j = 0; j < k; j++) {
int a;
scanf("%d", &a);
g[i].push_back(a);
}
}
for(int i = 0; i < n; i++)
scanf("%d%d", &p[i].x, &p[i].y);
int cnt = 0;
for(int i = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++) {
e[cnt].u = i;
e[cnt].v = j;
e[cnt++].w = caldist(p[i - 1], p[j - 1]);
}
// Kruscal算法
sort(e, e + cnt, cmp);
UFInit(n);
int ans = kruskal(cnt);
for(int i = 0; i < (1 << q); i++) {
UFInit(n);
int w = 0;
for(int j = 0; j < q; j++) {
if((i >> j) & 1)
continue;
w += cost[j];
for(int k = 1; k < (int)g[j].size(); k++)
Union(g[j][k], g[j][0]);
}
int t = kruskal(cnt);
if(t + w < ans)
ans = t + w;
}
printf("%d\n", ans);
if(t)
printf("\n");
}
return 0;
}