洛谷P1194 買禮物

題目描述

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

輸入樣例2

3 3
0 2 4
2 0 2
4 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 long
using 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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章