洛谷P1194 买礼物

来源:互联网 发布:大路口车流量数据 编辑:程序博客网 时间:2024/04/27 20:41

题目描述

又到了一年一度的明明生日了,明明想要买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 10

输入样例2

3 30 2 42 0 24 2 0

输出样例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。
n个物品都要买,就相当于把n个物品间接连通,又要用最小的代价,于是就可以拿最小生成树搞一搞。
代码如下

#include<iostream>#include<cstdio>#include<queue>#include<cstring>#include<algorithm>#define LL long longusing namespace std;const int size = 2000100;int f[size];int find(int x){    if(f[x] == x)        return x;    return f[x] = find(f[x]);}int a,b;LL tot = 0;struct dc{    int f,t,d;}l[size];bool cmp(dc a,dc b){    return a.d < b.d;}int main(){    scanf("%d%d",&a,&b);    for(int i = 1 ; i <= b ; i ++)    {        for(int j = 1 ; j <= b ; j ++)        {            int in;            scanf("%d",&in);            if(in)            {                tot ++;                l[tot].f = i , l[tot].t = j , l[tot].d = in;            }        }    }    sort(l+1,l+tot+1,cmp);    for(int i = 1 ; i <= b ; i ++)        f[i] = i;    LL ans = 0;    for(int i = 1 ; i <= tot ; i ++)    {        int ff = find(l[i].f) , ft = find(l[i].t);        if(ff != ft)        {            f[ff] = ft;            ans += l[i].d;        }    }    for(int i = 1 ; i <= b ; i ++)        if(f[i] == i)            ans += a;    printf("%lld\n",ans);    return 0;} 
0 0