今天也是scy菜鸡的一天(最小生成树

题目描述
又到了一年一度的明明生日了,明明想要买BB样东西,巧的是,这BB样东西价格都是AA元。

但是,商店老板说最近有促销活动,也就是:

如果你买了第II样东西,再买第JJ样,那么就可以只花K_{I,J}K
I,J

元,更巧的是,K_{I,J}K
I,J

竟然等于K_{J,I}K
J,I

现在明明想知道,他最少要花多少钱。

输入格式
第一行两个整数,A,BA,B。

接下来BB行,每行BB个数,第II行第JJ个为K_{I,J}K
I,J

我们保证K_{I,J}=K_{J,I}K
I,J

=K
J,I

并且K_{I,I}=0K
I,I

=0。

特别的,如果K_{I,J}=0K
I,J

=0,那么表示这两样东西之间不会导致优惠。

输出格式
一个整数,为最小要花的钱数。

输入输出样例
输入 #1复制
1 1
0

输出 #1复制
1
输入 #2复制
3 3
0 2 4
2 0 2
4 2 0
输出 #2复制
7
说明/提示
样例解释22

先买第22样东西,花费33元,接下来因为优惠,买1,31,3样都只要22元,共77元。

(同时满足多个“优惠”的时候,聪明的明明当然不会选择用44元买剩下那件,而选择用22元。)

数据规模

对于30%30%的数据,1 \le B \le 101≤B≤10。

对于100%100%的数据,1 \le B \le 500,0 \le A,K_{I,J} \le 10001≤B≤500,0≤A,K
I,J

≤1000。
思路:先求出最小生成树再加上一个原价(因为第一个买的没优惠)
注意:在洛谷题解中我看到这样一组if(i<=j&&x!=0),本来我以为我理解错了,后来发现x==0可能只是跟正常人理解不太一样qaq
如果有优惠就建边然后跑一遍kruskal就行了

#include<bits/stdc++.h>
using namespace std;

const int N=500+10;
int pr[N][N];
int a,b;
const int INF=0x3f3f3f3f;
int dis[N];
bool jud[N];
int pri;
void prim(){
	for(int i=0;i<b+1;i++){
		int t=-1;
		for(int j=0;j<=b;j++){
			if(!jud[j]&&(t==-1||dis[j]<dis[t])){
				t=j;
			}
			
			
		}
			jud[t]=1;
			if(i){
				pri+=dis[t];
			}
		for(int j=0;j<=b;j++){
			dis[j]=min(dis[j],pr[t][j]);
		}
	}
	
}
int main(){
	cin>>a>>b;
	for(int i=1;i<=b;i++){
		for(int j=1;j<=b;j++){
			cin>>pr[i][j];
			if(pr[i][j]==0&&i!=j){
				pr[i][j]=INF;
			}
		}
	}
	for(int i=1;i<=b;i++){
		pr[0][i]=a;
	}
	memset(dis,0x3f,sizeof dis);
	prim();
	cout<<pri;
	
	
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值