题意:买n个东西,这些东西有个原价m,若买东西i,则东西j降到a[i][j]元,求买n个东西最少的钱.
做法:若买i后买j的价钱a[i][j]比m小,那么连一条无向边,跑一波最小生成树.
看剩下还有几个点没连进去的就直接按原价买..
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <queue> 7 #include <stack> 8 #include <map> 9 #define ll long long 10 #define out(a) printf("%d",a) 11 #define ln printf(" ") 12 const int N=3e5+50050; 13 const int MOD=1e9+7; 14 using namespace std; 15 int n,m,x; 16 int tot=0,ans=0,cnt=0; 17 int pre[N]; 18 struct node 19 { 20 int x,y,cost; 21 }a[N]; 22 int read() 23 { 24 int s=0,t=1; char c; 25 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 26 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 27 return s*t; 28 } 29 ll readl() 30 { 31 ll s=0,t=1; char c; 32 while (c<'0'||c>'9'){if (c=='-') t=-1; c=getchar();} 33 while (c>='0'&&c<='9'){s=s*10+c-'0'; c=getchar();} 34 return s*t; 35 } 36 bool cmp(node a,node b) 37 { 38 return a.cost<b.cost; 39 } 40 int find(int x) 41 { 42 if (pre[x]==x) return x; 43 else return pre[x]=find(pre[x]); 44 } 45 void Kruskal() 46 { 47 for (int i=1;i<=tot;i++){ 48 int x=find(a[i].x),y=find(a[i].y); 49 if (x!=y){ 50 ans+=a[i].cost; 51 pre[x]=y; cnt++; 52 } 53 if (cnt==n-1) return; 54 } 55 } 56 int main() 57 { 58 m=read(),n=read(); 59 for (int i=1;i<=n;i++){ 60 pre[i]=i; 61 for (int j=1;j<=n;j++){ 62 x=read(); 63 if (x!=0&&x<m) a[++tot].x=i,a[tot].y=j,a[tot].cost=x; 64 } 65 } 66 sort(a+1,a+tot+1,cmp); 67 Kruskal(); 68 ans+=(n-cnt)*m; 69 out(ans); 70 return 0; 71 }