题目描述
又到了一年一度的明明生日了,明明想要买BB样东西,巧的是,这BB样东西价格都是AA元。
但是,商店老板说最近有促销活动,也就是:
如果你买了第II样东西,再买第JJ样,那么就可以只花K_{I,J}KI,J元,更巧的是,K_{I,J}KI,J竟然等于K_{J,I}KJ,I。
现在明明想知道,他最少要花多少钱。
输入输出格式
输入格式:第一行两个整数,A,BA,B。
接下来BB行,每行BB个数,第II行第JJ个为K_{I,J}KI,J。
我们保证K_{I,J}=K_{J,I}KI,J=KJ,I并且K_{I,I}=0KI,I=0。
特别的,如果K_{I,J}=0KI,J=0,那么表示这两样东西之间不会导致优惠。
输出格式:一个整数,为最小要花的钱数。
输入输出样例
说明
样例解释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,KI,J≤1000。
2018.7.25新添数据一组
蒟蒻博主又回来啦
图论作业做到自闭,于是来洛谷摸鱼qwq
答案目测是最小生成树的边权之和加上一个单价,想了想似乎超过单价的边权就不需要了,于是把这些边删掉,分别求每一个连通块的最小生成树,最后加上连通块个数*单价。
#include<iostream> using namespace std; const int N = 1005; int n,m,ans,v[N][N],dis[N]; bool b[N]; int main() { cin>>m>>n; for(int i=1;i<=n;++i) for(int j=1;j<=n;j++) { cin>>v[i][j]; if(v[i][j]>m) v[i][j] = 0; } while(1) { int u = -1; for(int i=1;i<=n;i++) if(!b[i]) u = i; if(u == -1) break; b[u] = 1; ans += m; for(int i=1;i<= n;++i) dis[i] = v[u][i]; dis[u] = -1; while(1) { int vv = -1,mn = 1e9+7; bool flg = 0; for(int i=1 ;i <= n;++i) if(dis[i] > 0 && dis[i] < mn) { mn = dis[i]; vv = i; flg = 1; } if(!flg) break; ans += mn; b[vv] = 1; dis[vv] = -1; for(int i=1;i<=n;++i) if(dis[i]>=0 && v[vv][i] && (dis[i] > v[vv][i] || dis[i] == 0)) dis[i] = v[vv][i]; } } cout<<ans<<endl; return 0; }