Buy or Build

来源:互联网 发布:知行理工app最新版 编辑:程序博客网 时间:2024/06/06 03:29

H - Buy or Build
Time Limit:3000MS Memory Limit:0KB
64bit IO Format:%lld & %llu

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.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 de ned 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).
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 le that contains all the relevant data. The rst 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 identi ed by a unique integer value ranging from 1 to n. The rst line is followed by q lines (one per subnetwork), all of them following the same pattern: The rst integer is the number of cities in the subnetwork. The second integer is the the cost of the subnetwork(not greater than 2  106). The remaining integers on the line (as many as the number of cities in the subnetwork) are the identi ers of the cities in the subnetwork. The last part of the le contains n lines that provide the coordinates of the cities (city 1 on the rst 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, your program has to write the optimal total cost to interconnect all cities. The outputs of two consecutive cases will be separated by a blank line.
A 115 Cities Instance Consider a 115 cities instance of the problem with 4 subnetworks (the 4 rst graphs in Figure 1).
As mentioned earlier the exact shape of a subnetwork is not relevant still, to keep gures 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 rst 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.
这里写图片描述
Figure 1: A 115 Cities Instance and a Solution (Buying the First and the Third Network)
Sample Explanation:
The sample input 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 2: The 7 City instance of the sample input
这里写图片描述
Figure 3
An optimal solution of the 7 City instance in which which the rst and second existing networkshave been bought while two extra edges (1,5) and (2,4) have been setup
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
题目大意:有n个城市,现在要在这n个城市中连通网络,有两种方法,一种是直接在两个城市之间连,一种是买一种套餐,该套餐中几个城市相互连通,要求用这两种方法求最小花费。
分析:由题意可得,与最小生成树类似,用kruskal算法,因为套餐的个数很少,所以我们可以枚举所用的套餐组合总数,将套餐中所包含的城市的父亲都更新为相同的点,再求最小生成树,每次枚举更新最小值即求得最小花费
代码:

#include<iostream>#include<algorithm>#include<string.h>#include<cstring>#include<vector>#include<cstdio>#define inf 0x3f3f3f3fusing namespace std;struct node{   int st;   int en;   int len;};int n,m,k;int fa[1100];int maze[1100][3];node E[1100000];int cost[10];vector<int> num[10];bool cmp(node n1,node n2){   return n1.len<n2.len;}int find(int x){    if(fa[x]==x)    return fa[x];    else    return fa[x]=find(fa[x]);}long long int kruskal(){    long long int ans=0;    for(int i=1;i<=k;i++)    {       int fx=find(E[i].st);       int fy=find(E[i].en);       if(fx!=fy)       {          ans+=E[i].len;          fa[fx]=fy;       }    }    return ans;}int main(){    int i,j,p,t,x,y,q,w,e,r;    long long int ans,ans1;    scanf("%d",&t);    for(i=1;i<=t;i++)    {        k=0;        scanf("%d%d",&n,&m);        for(j=0;j<m;j++)        num[j].clear();        for(j=0;j<m;j++)        {            scanf("%d%d",&x,&cost[j]);            for(p=0;p<x;p++)            {               scanf("%d",&y);               num[j].push_back(y);             }        }        for(j=1;j<=n;j++)        scanf("%d%d",&maze[j][1],&maze[j][2]);        for(j=1;j<=n;j++)        for(p=j+1;p<=n;p++)        {           k++;           E[k].st=j;           E[k].en=p;           E[k].len=(maze[j][1]-maze[p][1])*(maze[j][1]-maze[p][1])+(maze[j][2]-maze[p][2])*(maze[j][2]-maze[p][2]);        }        sort(E+1,E+k+1,cmp);        for(j=1;j<=n;j++)        fa[j]=j;        ans=kruskal();//先求一次不买套餐需要的费用        for(j=1;j<(1<<m);j++)//此处用到二进制枚举子集        {            ans1=0;            for(q=1;q<=n;q++)            fa[q]=q;            for(w=0;w<m;w++)            {                if(!(j&(1<<w)))                continue;                ans1+=cost[w];                e=find(num[w][0]);                for(p=1;p<num[w].size();p++)                {                    r=find(num[w][p]);                    if(e!=r)                    fa[r]=e;                }            }            ans=min(ans,ans1+kruskal());//套餐费用与普通费用加起来与ans取最小值        }        printf("%lld\n",ans);        if(i!=t)        printf("\n");    }    getchar();    getchar();    return 0;}
0 0
原创粉丝点击