目录
最小生成树概念
给定一个无向图,在图中选择若干条边把图的所有节点连起来
要求边长之和最小,在图论中,叫做求最小生成树
Prim求最小生成树
初始化准备:
dist[i]=i点到生成树集合的最短距离 初始化dist[i]=0x3f3f3f3f dist[1]=0
稠密图g[][]初始化0x3f3f3f3f
n次循环
{
1、从1~n点中找到未标记的点中,离生成树集合最近的点
2、如果是孤立点且不是第一个节点(dist[t]==0x3f3f3f3f)则不可能生成最小生成树
3、标记该点
4、(如果不是第一个节点)记录最小生成树边权之和
5、用该点更新其他点到集合的最小距离
}
public static int prim() { Arrays.fill(dist,0x3f3f3f3f); dist[1]=0; int res=0; for(int i=0;i<n;i++) { int t=-1; for(int j=1;j<=n;j++) //找到离集合最近的点 if(st[j]==0&&(t==-1||dist[j]<dist[t])) t=j; if(i!=0&&dist[t]==0x3f3f3f3f) return 0x3f3f3f3f; st[t]=1; if(i!=0) res+=dist[t]; for(int j=1;j<=n;j++) //用该点更新其他点到集合的最小距离 dist[j]=Math.min(dist[j],g[t][j]); } return res; }
联系:Dijkstra算法是更新到起始点的距离,Prim是更新到集合S的距离
/*
*道阻且长,行则将至*
author:Roye_ack
*/
import java.util.*;
import java.io.*;
import java.math.*;
class Main
{
static PrintWriter wt=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int N=510;
static int n,m;
static int[][] g=new int [N][N];
static int[] dist=new int[N];
static int[] st=new int[N];
static int[] pre=new int[N];
public static int prim()
{
Arrays.fill(dist,0x3f3f3f3f);
dist[1]=0;
int res=0;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++) //找到离集合最近的点
if(st[j]==0&&(t==-1||dist[j]<dist[t])) t=j;
if(i!=0&&dist[t]==0x3f3f3f3f) return 0x3f3f3f3f;
st[t]=1;
if(i!=0) res+=dist[t];
for(int j=1;j<=n;j++) //用该点更新其他点到集合的最小距离
if(dist[j]>g[t][j])
{
dist[j]=g[t][j];
pre[j]=t; //则j的前驱节点就是t
}
}
return res;
}
public static void getPath()
{
for(int i=n;i>1;i--)
wt.println(i+" "+pre[i]+" ");
}
public static void main(String[] args) throws IOException
{
n=rd.nextInt();
m=rd.nextInt();
for(int i=1;i<=n;i++) Arrays.fill(g[i],0x3f3f3f3f);
while(m-->0)
{
int a=rd.nextInt(),b=rd.nextInt(),c=rd.nextInt();
g[a][b]=g[b][a]=Math.min(g[a][b],c);
}
int t=prim();
if(t==0x3f3f3f3f) wt.println("impossible");
else wt.println(t);
//getPath();
wt.flush();
}
static class rd
{
static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tk=new StringTokenizer("");
static String nextLine() throws IOException
{
return bf.readLine();
}
static String next() throws IOException
{
while(!tk.hasMoreTokens()) tk=new StringTokenizer(bf.readLine());
return tk.nextToken();
}
static int nextInt() throws IOException
{
return Integer.parseInt(next());
}
static double nextDouble() throws IOException
{
return Double.parseDouble(next());
}
static long nextLong() throws IOException
{
return Long.parseLong(next());
}
static BigInteger nextBig() throws IOException
{
BigInteger d=new BigInteger(rd.nextLine());
return d;
}
}
}
class PII implements Comparable<PII>
{
public int x;
public int y;
public PII(int x,int y)
{
this.x=x;
this.y=y;
}
public int compareTo(PII o)
{
return Integer.compare(x,o.x);
}
}
Kruskal求最小生成树
- 将所有边权值按从小到大排序
- 遍历每两条边a b,如果ab不连通,则将ab放入集合中,记录cnt边数
- 如果cnt<n-1(n个点n-1条边)则说明不能生成最小生成树
/*
*道阻且长,行则将至*
author:Roye_ack
*/
import java.util.*;
import java.io.*;
import java.math.*;
class Main
{
static PrintWriter wt=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int N=101000,M=2*N;
static int n,m;
static int[] p=new int[N];
static Node[] node=new Node[M];
public static int find(int x)
{
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
public static void main(String[] args) throws IOException
{
n=rd.nextInt();
m=rd.nextInt();
for(int i=1;i<=n;i++) p[i]=i;
for(int i=0;i<m;i++)
{
int a=rd.nextInt(),b=rd.nextInt(),c=rd.nextInt();
node[i]=new Node(a,b,c);
}
//按边权值从小到大排序
Arrays.sort(node,0,m,(o1,o2)->o1.c-o2.c);
//循环每一条边
int cnt=0,res=0;
for(int i=0;i<m;i++)
{
int a=find(node[i].a),b=find(node[i].b);
if(a!=b)
{
p[a]=b;
cnt++;
res+=node[i].c;
}
}
if(cnt<n-1) wt.print("impossible"); //n个点n-1条边
else wt.print(res);
wt.flush();
}
static class rd
{
static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tk=new StringTokenizer("");
static String nextLine() throws IOException
{
return bf.readLine();
}
static String next() throws IOException
{
while(!tk.hasMoreTokens()) tk=new StringTokenizer(bf.readLine());
return tk.nextToken();
}
static int nextInt() throws IOException
{
return Integer.parseInt(next());
}
static double nextDouble() throws IOException
{
return Double.parseDouble(next());
}
static long nextLong() throws IOException
{
return Long.parseLong(next());
}
static BigInteger nextBig() throws IOException
{
BigInteger d=new BigInteger(rd.nextLine());
return d;
}
}
}
class Node
{
int a,b,c;
public Node(int aa,int bb,int cc)
{
a=aa;
b=bb;
c=cc;
}
}