持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情
买礼物
题目描述
又到了一年一度的明明生日了,明明想要买 样东西,巧的是,这 样东西价格都是 元。
但是,商店老板说最近有促销活动,也就是:
如果你买了第 样东西,再买第 样,那么就可以只花 元,更巧的是, 竟然等于 。
现在明明想知道,他最少要花多少钱。
输入格式
第一行两个整数,。
接下来 行,每行 个数,第 行第 个为 。
我们保证 并且 。
特别的,如果 ,那么表示这两样东西之间不会导致优惠。
输出格式
一个整数,为最小要花的钱数。
样例 #1
样例输入 #1
1 1
0
样例输出 #1
1
样例 #2
样例输入 #2
3 3
0 2 4
2 0 2
4 2 0
样例输出 #2
7
提示
样例解释 。
先买第 样东西,花费 元,接下来因为优惠,买 样都只要 元,共 元。
(同时满足多个“优惠”的时候,聪明的明明当然不会选择用 元买剩下那件,而选择用 元。)
数据规模
对于 的数据,。
对于 的数据,。
2018.7.25新添数据一组
分析
这题是个最小生成树的题目,但是这题与我之前做过的那个昂贵的聘礼有异曲同工之妙,就是可以引入一个超级源点给每条边连一下,然后最小生成树克鲁斯卡尔大功告成!
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=1e6+10;
int a,b,res=0,fa[N];
struct pi{
int a,b,w;
}edge[N];
bool cmp(pi x,pi y){
return x.w<y.w?1:0;
}
int find(int x){
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
int main(){
cin>>a>>b;
int k=0;
for(int i=0;i<=b;i++){
fa[i]=i;
}
for(int i=1;i<=b;i++){
for(int j=1;j<=b;j++){
int w;
cin>>w;
if(i!=j && w!=0)
edge[++k]={i,j,w};
}
}
for(int i=1;i<=b;i++){
edge[++k]={0,i,a};
edge[++k]={i,0,a};
}
sort(edge+1,edge+k+1,cmp);
for(int i=1;i<=k;i++){
int a=edge[i].a,b=edge[i].b,w=edge[i].w;
int x=find(a),y=find(b);
if(x!=y){
res+=w;
fa[x]=y;
}
}
cout<<res<<endl;
}
希望能帮助到大家()!