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 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

题意:给你n个点,q个套餐。其中套餐表示你只需要支付该套餐的钱,就可以让该套餐上的城市连通。接下来是n个城市的坐标。现在要你求出能连通n个点的最小的价值

思路:这道题目还是难了我一天,之前许多的细节问题都没有考虑好。

实际上你只需要先找出当前的最小生成树,然后再跟你选了几个套餐之后的最小生成树比较,找出最小值就可以了!

AC代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int N=1000+5;
int f[N];
int n,m;
int x[N],y[N],r[N];
int tao[8][N];
int val[8],cnt,q1[8];
struct p
{
    int u,v,w;
}num[N*(N-1)/2];

int find(int x)
{
    if(x!=f[x])
        f[x]=find(f[x]);
    return f[x];
}

bool cmp(p x,p y)
{
    return x.w<y.w;
}

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

    int i,tot=0,ans=0;
    for(i=0;i<cnt&&tot<n-1;i++)
    {
        int a=find(num[i].u);
        int b=find(num[i].v);
        if(a==b)
            continue;
        ans+=num[i].w;
        f[a]=b;
        tot--;
    }
    return ans;
}

int juli(int i,int j)
{
    return (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
}
int main()
{
    int i,j,q,sum,k;
    while(scanf("%d %d",&n,&q)!=EOF)
    {
        for(i=0;i<q;i++)
        {
            scanf("%d %d",&q1[i],&val[i]);
            for(j=0;j<q1[i];j++)
                scanf("%d",&tao[i][j]);
        }
        for(i=1;i<=n;i++)
            scanf("%d %d",&x[i],&y[i]);
        cnt=0;
        for(i=1;i<=n;i++)
        {
            for(j=i+1;j<=n;j++)
            {
                num[cnt].u=i;
                num[cnt].v=j;
                num[cnt++].w=juli(i,j);
            }
        }
        sort(num,num+cnt,cmp);
        init();
        sum=kruskal();
        for(int s=1;s<(1<<q);s++)  //枚举你要选几个套餐
        {
            int cost=0;

            init();
            for(j=0;j<q;j++)
            {
                if(!((s>>j)&1)) continue;
                cost+=val[j];
                for(int k=1;k<q1[j];k++)
                {
                    int a=find(tao[j][k]);
                    int b=find(tao[j][0]);
                    if(a!=b)
                        f[a]=b;
                }

            }
            sum=min(cost+kruskal(),sum);       //加套餐之后的最小生成树的值
        }
        printf("%d\n",sum);
    }

    return 0;
}
时间: 2024-10-08 08:16:29

POJ 2784 Buy or Build的相关文章

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

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

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 Borduri

poj 2828 Buy Tickets 【线段树点更新】

题目:poj 2828 Buy Tickets 题意:有n个人排队,每个人有一个价值和要插的位置,然后当要插的位置上有人时所有的人向后移动一位当这个插入到这儿,如果没有直接插进去. 分析:分析发现直接插入移动的话花时间太多,我们可不可以用逆向思维.从后往前来,因为最后一个位置是肯定能确定的,而其他的则插入空的第某个位置. 比如第一组样例: 4 0 77 1 51 1 33 2 69 开始时候位置都为空 编号0 1 2 3 首先从最后一个来2 69 第二个位置空,则可以直接放 然后编号变为0 1

poj 2828 Buy Tickets

Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 13277   Accepted: 6595 Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue- The Lunar New Year wa

POJ 2828 Buy Tickets 线段树解法

此题应用线段树的方法非常巧妙.没做过真的难想得出是这么想的. 是一个逆向思维的运用. 其实一看到这道题目我就想到要运用逆向思维的了,但是就是没那么容易想通的. 思路: 1 要从后面往前更新线段树 2 线段树记录的是当前区间还剩下多少个记录空间 3 因为后面的插入会使得前面的插入往后退,那么前面插入的下标如果大于前面可以插入的空间,就需要往后退了. 好难理解的操作.仔细观察一下下面update这个函数吧. 二分地去查找适合的插入位置,把插入操作时间效率提高到 O(lgn),如果使用一般方法插入操作

POJ 2827 Buy Tickets(排队问题,线段树应用)

POJ 2827 Buy Tickets(排队问题,线段树应用) ACM 题目地址:POJ 2827 Buy Tickets 题意: 排队买票时候插队. 给出一些数对,分别代表某个人的想要插入的位置Pos_i和他的Val_i,求出最后的队列的val顺序. 分析: 也是一道很巧妙的题目. 刚开始天真的以为sort一下就行了.wa了一发后发现我错了... 原来可以很巧妙的用线段树做.由于某个人想要插入posi位置,插入后他就在posi位置上了,但是可能其他人会插到他前面来,他的位置就会变成[在他后面

线段树(单点更新) POJ 2828 Buy tickets

题目传送门 1 /* 2 结点存储下面有几个空位 3 每次从根结点往下找找到该插入的位置, 4 同时更新每个节点的值 5 */ 6 #include <cstdio> 7 #define lson l, m, rt << 1 8 #define rson m+1, r, rt << 1 | 1 9 10 const int MAX_N = 200000 + 10; 11 int pos[MAX_N], val[MAX_N]; 12 int sum[MAX_N <&

【POJ】Buy Tickets(线段树)

点更新用法很巧妙的一道题.倒序很容易的找到该人的位置,而update操作中需要不断的变化下标才能合理的插入.看了别人写的代码,学习了. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <map> 5 using namespace std; 6 7 const int maxn = 2e5 + 10; 8 int sumv[maxn << 2],