題目描述
又到了一年一度的明明生日了,明明想要買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;
}