P1194 买礼物 洛谷

https://www.luogu.org/problem/show?pid=1194

题目描述

又到了一年一度的明明生日了,明明想要买B样东西,巧的是,这B样东西价格都是A元。

但是,商店老板说最近有促销活动,也就是:

如果你买了第I样东西,再买第J样,那么就可以只花K[I,J]元,更巧的是,K[I,J]竟然等于K[J,I]。

现在明明想知道,他最少要花多少钱。

输入输出格式

输入格式:

 

第一行两个整数,A,B。

接下来B行,每行B个数,第I行第J个为K[I,J]。

我们保证K[I,J]=K[J,I]并且K[I,I]=0。

特别的,如果K[I,J]=0,那么表示这两样东西之间不会导致优惠。

 

输出格式:

 

仅一行一个整数,为最小要花的钱数。

 

输入输出样例

输入样例#1:
【样例输入1】
1 1
0
【样例输入2】
3 3
0 2 4
2 0 2
4 2 0
输出样例#1:
【样例输出1】
1
【样例输出2】
7

说明

样例解释2

先买第2样东西,花费3元,接下来因为优惠,买1,3样都只要2元,共7元。

(同时满足多个“优惠”的时候,聪明的明明当然不会选择用4元买剩下那件,而选择用2元。)

数据规模

对于30%的数据,1<=B<=10。

对于100%的数据,1<=B<=500,0<=A,K[I,J]<=1000。

 

#include <algorithm>
#include <iostream>
#define maxn 10000007

using namespace std;

int a,b,tot,num,ans;
int fa[1005];
int dis;
struct node
{
    int x,y,z;
}w[250000];

void add(int a,int b,int c)
{
    tot++;
    w[tot].x=a;
    w[tot].y=b;
    w[tot].z=c;
}

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

bool cmp(node a,node b)
{
    return a.z<b.z;
}

int main()
{
    cin>>a>>b;
    for(int i=1;i<=b;i++)    fa[i]=i;
    for(int i=1;i<=b;i++)
        for(int j=1;j<=b;j++)
        {
            cin>>dis;
            if(i>=j&&dis!=0)    add(i,j,dis);
        }
    for(int i=1;i<=b;i++)    add(0,i,a);
    sort(w+1,w+tot+1,cmp);
    for(int i=1;i<=tot;i++)
    {
        int xx=find(w[i].x),yy=find(w[i].y);
        if(xx!=yy)
        {
            fa[xx]=yy;
            num++;
            ans+=w[i].z;
        }
        if(num>b)    break;
    }
    cout<<ans;
    return 0;
}

 

posted @ 2017-03-10 21:07  Aptal丶  阅读(220)  评论(0编辑  收藏  举报