洛谷——P1194 买礼物
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 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<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 500100 using namespace std; int n,m,x,y,z,fx,fy,tot,sum,ans,fa[N]; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } struct Node { int x,y,z; }node[N]; int cmp(Node a,Node b) { return a.z<b.z; } int find(int x) { if(fa[x]==x) return x; fa[x]=find(fa[x]); return fa[x]; } int main() { m=read(),n=read(); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { z=read(); if(z!=0) { ++tot; node[tot].x=i; node[tot].y=j; node[tot].z=z; } } sort(node+1,node+1+tot,cmp); for(int i=1;i<=tot;i++) { x=node[i].x,y=node[i].y; fx=find(x),fy=find(y); if(fx==fy) continue; else fa[fy]=fx; ans+=node[i].z; sum++; if(sum==n-1) break; } for(int i=1;i<=n;i++) if(fa[i]==i) ans+=m; printf("%d",ans); return 0; }