1. 程式人生 > >luogu P1194 買禮物

luogu P1194 買禮物

表示 輸出格式 col 輸入輸出格式 def 最小生成樹 老板 truct code

題目描述

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

最小生成樹,最後加上沒father合並的

#include<cstdio>
#include<algorithm>
using namespace std;

#define N 500006
int A,B;
int n;
struct node{
    int u,v,w;
}edge[N];
int read(){
    int x=0,f=1;char c=getchar();
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10
+c-0;c=getchar();}return x*f; } bool cmp(node a,node b) { return a.w<b.w; } int father[N]; int find(int x) { if(x!=father[x])father[x]=find(father[x]); return father[x]; } int cnt,ans; int num; inline void kruskal() { sort(edge+1,edge+num+1,cmp); for(int i = 1;i <= num;i++) { int fx = find(edge[i].u),fy = find(edge[i].v); if(fx != fy) { cnt++; ans += edge[i].w; father[fy] = fx; } } } int main() { A=read();B=read(); for (int i = 1;i <= B;i ++)father[i] = i; for (int i = 1;i <= B;i ++) for (int j = 1;j <= B;j ++) { int a; a=read(); if(i<j&&a!=0) edge[++num].u=i,edge[num].v=j,edge[num].w=a; } kruskal(); for (int i = 1;i <= B;i ++) if (father[i] == i)ans += A; printf("%d",ans); return 0; }

luogu P1194 買禮物