您的位置:首页 > 产品设计 > UI/UE

1151 - Buy or Build

2015-07-22 19:26 405 查看
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 q1 then each subnetwork c ( 1cq ) 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 input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.

Each test case is described by one input file that contains all the relevant data. The first line contains the number n of cities in the country ( 1n1000 ) followed by the number q of existing subnetworks ( 0q8 ). 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

For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.

For each input file, your program has to write the optimal total cost to interconnect all cities.

Sample Input

1

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

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 1: A 115 Cities Instance and a Solution (Buying the First and the Third Network)



Figure 2: The 7 City instance of the first sample input



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) have been setup



我有话说:

这道题比较裸,就是一个最小生成树。但是如果枚举选择的方案在进行prim或者kruskal算法。由于枚举量为2^q,给边排序需要的时间复杂度为n^2logn,而排序后每次kruskal算法的时间复杂度为n^2,所以最后的总时间复杂度你想想吧。

采取紫书上的优化策略。先求一次原图中的最小生成树。得到n-1条边。然后枚举完套餐后只考虑套餐和这n-1条边。因为,在最小生成树中,有一些边是不会进入的。那些已经属于同一个联通分量的边。所以只要那些在原来算法中被扔掉的边是不用考虑的。情况一,套餐中包含原来被扔掉的边,那么就只有购买套餐有可能使它们进入最小生成树,只要计算套餐和n-1条边即可。

情况二。套餐中完全不包含原来扔掉的边。那么就更不用考虑了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int maxn=1000+10;
const int maxq=8;
int n;
int x[maxn],y[maxn],cost[maxq];
vector<int>subn[maxq];
int p[maxn];
int findest(int x){
return p[x]==x?x:p[x]=findest(p[x]);
}
struct Edge{
int u,v,d;
Edge(int u,int v,int d):u(u),v(v),d(d){}
bool operator < (const Edge& rhs)const{
return d<rhs.d;
}
};
int Kruskal(int cnt,const vector<Edge>& e,vector<Edge>& used)
{
if(cnt==1)return 0;
used.clear();
int m=e.size();
int ans=0;
for(int i=0;i<m;i++){
int u=findest(e[i].u),v=findest(e[i].v);
int d=e[i].d;
if(u!=v){
p[u]=v;
ans+=d;
used.push_back(e[i]);
if(--cnt==1)break;
}
}
return ans;
}
int main() {
int T,q;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&q);
for(int i=0;i<q;i++){
int cnt,u;
scanf("%d%d",&cnt,&cost[i]);
subn[i].clear();
while(cnt--){
scanf("%d",&u);
subn[i].push_back(u-1);
}
}
for(int i=0;i<n;i++)scanf("%d%d",&x[i],&y[i]);
vector<Edge>e,need;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
int c=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
e.push_back(Edge(i,j,c));
}
}
for(int i=0;i<n;i++)p[i]=i;
sort(e.begin(),e.end());
int ans=Kruskal(n,e,need);
for(int mask=0;mask<(1<<q);mask++){
for(int i=0;i<n;i++)p[i]=i;
int cnt=n,c=0;
for(int i=0;i<q;i++)if(mask&(1<<i)){
c+=cost[i];
for(int j=1;j<subn[i].size();j++){
int u=findest(subn[i][j]),v=findest(subn[i][0]);
if(u!=v){p[u]=v;cnt--;}
}
}
vector<Edge>dummy;
ans=min(ans,c+Kruskal(cnt,need,dummy));
}
printf("%d\n",ans);
if(T)printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: