题目链接:​​https://www.luogu.org/problemnew/show/P1194​

思路:

kruskal

值得注意的是如果i==j,那么这条路径就不要存了,在i!=j的情况下,如果k[i][j]==0
说明先买i之后没有对j优惠,那么i到j这条路径应该存为n就是原本每一个礼物的价格。

package 图论;
//ac
//思路kruskal
//值得注意的是如果i==j,那么这条路径就不要存了,在i!=j的情况下,如果k[i][j]==0
//说明先买i之后没有对j优惠,那么i到j这条路径应该存为n就是原本每一个礼物的价格。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class P1194买礼物 {
static int n;
static int m;
static int []p;
static int []rank;
public static void init() {
for(int i=1;i<=m;i++) {
p[i]=-1;
rank[i]=0;
}
}
public static int find_root(int x) {
int x_root=x;
while(p[x_root]!=-1) {
x_root=p[x_root];
}
return x_root;
}
public static int union(int x,int y) {
int x_root=find_root(x);
int y_root=find_root(y);
if(x_root==y_root) {
return 0;
}
else {
if(rank[x_root]>rank[y_root]) {
p[y_root]=x_root;
}
else if(rank[x_root]<rank[y_root]) {
p[x_root]=y_root;
}
else {
p[x_root]=y_root;
rank[y_root]++;
}
return 1;
}
}
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
n=in.nextInt();
m=in.nextInt();
p=new int[m+1];
rank=new int[m+1];
init();
List<mai>list=new ArrayList<mai>();
for(int i=1;i<=m;i++) {
for(int j=1;j<=m;j++) {
int a=in.nextInt();
if(i!=j){
if(a==0)a=n;
list.add(new mai(i,j,a));
}
}
}
Collections.sort(list);
int k=0;
int sum=n;
for(int i=0;i<list.size();i++) {
if(k==m-1)break;
if(union(list.get(i).f,list.get(i).t)==1) {
k++;
sum+=list.get(i).quan;
}
}
if(sum<n*m)System.out.println(sum);
else System.out.println(n*m);
}

}
class mai implements java.lang.Comparable<mai>{
int f;
int t;
int quan;
public int compareTo(mai o) {
return this.quan-o.quan;
}

public mai(int f, int t, int quan) {
super();
this.f = f;
this.t = t;
this.quan = quan;
}

}