Buy or Build (poj 2784 最小生成树)

Buy or Build

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 1348   Accepted: 533

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

Southwestern Europe 2005

题意:n个城市,告诉每个城市的坐标,还有q个联通块,现在要把这n个城市连起来,可以购买联通块(每个有一定的费用),或者新建一条边(费用为点之间的距离的平方),问最小费用是多少。

思路:q很小,二进制枚举选哪些块,每次kruskal一遍,求最小值。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

const int maxn = 1005;
const int MAXN = 500500;

struct Node
{
    int x,y;
}node[maxn];

struct Edge
{
    int u,v,len;
    bool operator<(const Edge &a)const
    {
        return len<a.len;
    }
}edge[MAXN];

int father[maxn],cost[10];
int n,q,num;
vector<int>g[10];

void init()
{
    for (int i=0;i<=n;i++)
        father[i]=i;
}

void addedge(int u,int v)
{
    edge[num].u=u;
    edge[num].v=v;
    edge[num++].len=(node[u].x-node[v].x)*(node[u].x-node[v].x)+(node[u].y-node[v].y)*(node[u].y-node[v].y);
}

int find_father(int x)
{
    if (x!=father[x])
        father[x]=find_father(father[x]);
    return father[x];
}

bool Union(int a,int b)
{
    int fa=find_father(a);
    int fb=find_father(b);
    if (fa==fb) return false;
    father[fa]=fb;
    return true;
}

int Kruskal()
{
    int ans=0;
    int cnt=0;
    for (int i=0;i<num;i++)
    {
        if (Union(edge[i].u,edge[i].v))
        {
            ans+=edge[i].len;
            cnt++;
        }
        if (cnt==n-1) break;
    }
    return ans;
}

void solve()
{
    init();
    int ans=Kruskal();
    for (int i=0;i<(1<<q);i++)
    {
        init();
        int all=0;
        for (int j=0;j<q;j++)
        {
            if (!((i>>j)&1)) continue;
            all+=cost[j];
            for (int k=1;k<g[j].size();k++)
                Union(g[j][k],g[j][0]);
        }
        ans=min(ans,all+Kruskal());
    }
    pf("%d\n",ans);
}

int main()
{
    int i,j,t,number,x;
//    sf(t);
//    while (t--)
    {
        sff(n,q);
        num=0;
        for (i=0;i<q;i++)
        {
            g[i].clear();
            sff(number,cost[i]);
            for (j=0;j<number;j++)
            {
                sf(x);
                g[i].push_back(x);
            }
        }
        for (i=1;i<=n;i++)
            sff(node[i].x,node[i].y);
        for (i=1;i<=n;i++)
            for (j=i+1;j<=n;j++)
                addedge(i,j);
        sort(edge,edge+num);
        solve();
//        if (t) puts("");
    }
    return 0;
}
/*
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
*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 07:33:32

Buy or Build (poj 2784 最小生成树)的相关文章

uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)

也是简单的最小生成树算法 不过添加了一些新的东西,需要对最小生成树算法 以及其中的 并查集的使用 有一些比较深入的理解. 处理问题的方法也有些复杂 #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int maxn = 1005; struct point { int x; int y; }pp[maxn]; s

【uva 1151】Buy or Build(图论 最小生成树)

题意:平面上有N个点(1≤N≤1000),若要新建边,费用是2点的欧几里德距离的平方.另外还有Q个套餐,每个套餐里的点互相联通,总费用为Ci.问让所有N个点连通的最小费用.(2组数据的输出之间要求有换行) 解法:利用二进制枚举套餐,时间复杂度是O(2QN2+N2logN).关于时间复杂度,枚举:二进制枚举为2Q,Kruskal为ElogE≍E≍N2:边排序:ElogE≍E≍N2.总的相加. 紫书上提到一个优化:不加任何套餐跑一遍MST(最小生成树),没有选的边便删除掉,因为以后加了套餐之后也选不

UVA 1151 Buy or Build (MST最小生成树,kruscal,变形)

题意:要使n个点之间能够互通,要使两点直接互通需要耗费它们之间的欧几里得距离的平方的权(注意不需要开方的),这说明每两个点都可以使其互通.接着又q个套餐可以选,一旦选了这些套餐,他们所包含的点自动就连起来了,所需要做的就是连上还未通的即可,q<=8.可以多买.求最小生成树所需的代价. 思路:与普通求MST不同的就是多了套餐,而且还可以多买.每个套餐有买或不买两种可能,那么有28种可能,即256种. 如果不买套餐,至少需要求1次MST是确定的,这个复杂度已经是O(n*n)了.还得考虑哪些餐套可以搭

POJ 2784 Buy or Build最小生成树

Buy or Build Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1360   Accepted: 539 Description World Wide Networks (WWN) is a leading company that operates large telecommunication networks. WWN would like to setup a new network in Borduri

poj——2031 最小生成树(MST) Kruskal算法

poj——2031 最小生成树(MST)  Kruskal算法 Building a Space Station Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 4985   Accepted: 2503 Description You are a member of the space station engineering team, and are assigned a task in the constructio

1151 - Buy or Build(二进制枚举子集 + 并查集)

这题LRJ书上翻译的有问题,书上说两点之间的cost是两点的欧几里得距离,而题目要求两点的距离是两点欧几里得距离的平方. 其余就没什么好说的了,裸的并查集,需要注意的就是二进制枚举子集的问题. 二进制枚举子集: for(int i = 0 ; i < (1 << s) ; i++){ /*s是集合元素的个数*/ for(int j = 0 ; j < s ; j++){ if(!(s >> j) & 1) continue; else{ } } } 140548

poj 1251(最小生成树)

Description The Head Elder of the tropical island of Lagrishan has a problem. A burst of foreign aid money was spent on extra roads between villages some years ago. But the jungle overtakes roads relentlessly, so the large road network is too expensi

POJ 2784 Buy or Build

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 whi

UVa 1151 Buy or Build (最小生成树+二进制法暴力求解)

题意:给定n个点,你的任务是让它们都连通.你可以新建一些边,费用等于两点距离的平方(当然越小越好),另外还有几种“套餐”,可以购买,你购买的话,那么有些边就可以连接起来, 每个“套餐”,也是要花费的,让你求出最少花费. 析:首先想到的是把所有情况都考虑算一下,然后找出最少的,先算没有“套餐”的,然后算有的,用二进制枚举的话,总时间复杂度为O(2qn2+n2logn),这个时间复杂度太大了吧,肯定会超时, 那么我们就可以优化一下,首先先算出来最小生成树,并且把每条边都保存下来,那么加了“套餐”之后