Kruskal模板
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#define maxn 2000000
using namespace std;
typedef long long LL;
bool flag=false;
struct point{
int x;
int y;
}p[200];
//点的集合,有些时候会直接给出点的编号,就不用建立结构体和数组了
//如果给的点是坐标,需给点进行编号
struct edge{
int start;
int end;
double w;//注意权值的数据类型
}e[30000];
//一定要注意边的集合元素至少是n*(n+1)/2个,n为点的数目
//直接写成n*n+n个元素保险
int father[200];//注意点的个数
int find(int x)
{
return father[x]==x?x:father[x]=find(father[x]);
}
//x为点的编号,返回的是它父亲节点的编号
bool cmp(const edge &a,const edge &b)
{
if(a.w<b.w) return true;
else return false;
}
double Kruskal(int n,int r)
//注意要修改返回值类型,返回权值之和,有时候也会判断能否形成MST,n为点的数目,r为边的数目
{
double ans=0;//注意其数据类型,与权值的数据类型相同,权值之和的累加器
for(int i=0;i<=n;i++)
father[i]=i;
//初始化并查集
sort(e,e+r,cmp);//排序,按权值从小到大排
int k=0;
for(int i=0;i<r;i++)
{
int x=find(e[i].start);int y=find(e[i].end);
if(x!=y) {k++;ans+=e[i].w;father[x]=y;}
}
if(k==n-1) return ans;//判断能否形成MST
else return 0;
}
int n,x,y;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&x,&y);
p[i].x=x,p[i].y=y;
}
int r=0;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
e[r].start=i;
e[r].end=j;
int x2=p[i].x-p[j].x;
int y2=p[i].y-p[j].y;
double dis=sqrt(x2*x2+y2*y2);//有时候会限定权值范围,即舍去一些边要注意
e[r].w=dis;
r++;
//依次记录每条边的起点、终点、权值并编号
}
}
int flag=(int)Kruskal(n,r);
if(flag) printf("%.1lf\n",Kruskal(n,r)*100);//如果成功找到
else printf("………………");//否则……………………
}
return 0;
}
prime模板(用邻接矩阵):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int map[200][200],lowcost[200];//map[][]代表的是邻接矩阵,注意点的个数,lowcost代表最小生成树里的点与不是最小生成树的点的边的权;
bool visit[200];//代表最小生成树这个集合即用过这个点就将其染黑;
int prime(int n)//注意返回值类型,返回的是权值,n代表点的数目
{
int min,sumw=0;//注意类型,与权值的类型相同
int k,c=0;
memset(visit,false,sizeof(visit));
visit[1]=true;
for(int i=1;i<=n;i++) //注意点的编号是从1开始
lowcost[i]=map[1][i];
for(int i=1;i<=n;i++)
{
min=INF;
for(int j=1;j<=n;j++)
{
if(!visit[j]&&min>lowcost[j])
{
min=lowcost[j];
k=j;
}
}
if(min==INF) break;
visit[k]=true;
sumw+=min;c++;
for(int j=1;j<=n;j++)
if(!visit[j]&&lowcost[j]>map[k][j])
lowcost[j]=map[k][j];
}
if(c==n-1) return sumw;//如果找到这个树,返回权值
else return 0;//没有找到,返回0
}
struct point{
int x;
int y;
}p[200]//点的集合,给出点的坐标,利用结构体将其编号
/*如果给的是点的坐标,
for(int i=1;i<=n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;i++)
{
int x2=p[i].x-p[j].x;
int y2=p[i].y-p[j].y;
double dis=sqrt(x2*x2-y2*y2);
map[i][j]=dis;
}
利用这个创造邻接矩阵*/
int main()
{
int n;
while(~scanf("%d",&n)&n)
{
for(int i=0;i<=200;i++)
for(int j=0;j<=200;j++)
map[i][j]=INF;//注意一定要初始化邻接矩阵
int n1=n-1;
while(n1--)
{
char start;int t;
cin>>start>>t;
while(t--)
{
char end;int w;
cin>>end>>w;
map[start-'A'+1][end-'A'+1]=w;
map[end-'A'+1][start-'A'+1]=w;
}//创造出邻接矩阵
}
printf("%d\n",prime(n));
}
return 0;
}
prime(邻接表):用的是最常规的结构体内带有指针表示链表,可以用链表或数组表示,然后用优先队列,进行选最小的边,现在还不是太会,努力以后一定补充完整。
以下程序参考于https://blog.csdn.net/qq_35644234/article/details/59106779
#include <iostream>
#include <cstdio>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
struct edge{
int toppoint;
int weight;
edge* next1;
};
struct top_pointlist{
edge * edge1;
};
struct Graph_List{
int toppoint_number;
int edge_number;
top_pointlist*list;
}g1;
void creatGraph(Graph_List&g)
{
cin>>g.toppoint_number>>g.edge_number;
g.list=new top_pointlist[g.toppoint_number];
int i;
for(int i=0;i<g.toppoint_number;i++)
{
g.list[i].edge1=NULL;
}
for(int i=0;i<g.edge_number;i++)
{
int start;
int end;
int weight;
cin>>start>>end>>weight;
edge*next=new edge;
next->toppoint=end-1;
next->weight=weight;
next->next1=NULL;
if(g.list[start-1].edge1==NULL) g.list[start-1].edge1=next;
else
{
edge* temp;
temp=g.list[start-1].edge1;
while(temp->next1)
{
temp=temp->next1;
}
temp->next1=next;
}
edge*next2=new edge;
next2->toppoint=start-1;
next2->weight=weight;
next2->next1=NULL;
if(g.list[end-1].edge1==NULL) g.list[end-1].edge1=next2;
else
{
edge* temp;
temp=g.list[end-1].edge1;
while(temp->next1)
{
temp=temp->next1;
}
temp->next1=next2;
}
}
}
void print(Graph_List g)//打印图
{
for(int i=0;i<g.toppoint_number;i++)
{
edge*next;
next=g.list[i].edge1;
while(next)
{
cout << "("<< next->toppoint <<")="<<next->weight << " ";
next = next->next1;
}
cout<<"<"<<endl;
}
}
struct close_edge{
int start;
int end;
int weight;
} c_edge[100];//边的个数
void prime(Graph_List g, int begin)
{
int w=0;//权的累加器,注意类型
for(int j=0;j<g.toppoint_number;j++)
c_edge[j].weight=INF;
edge*temp= g.list[begin-1].edge1;
while(temp)
{
c_edge[temp->toppoint].end=temp->toppoint;
c_edge[temp->toppoint].start=begin-1;
c_edge[temp->toppoint].weight = temp->weight;
temp = temp->next1;
}
c_edge[begin - 1].weight = -1;
for (int j = 1; j < g.toppoint_number; j++) {
int min = INF;
int k;
int index;
/*寻找数组c_edge中权重最小的那个边*/
for (k = 0; k < g.toppoint_number; k++) {
if (c_edge[k].weight != -1) {
if (c_edge[k].weight < min) {
min = c_edge[k].weight;
index = k;
}
}
}
if(min!=INF) w+=min;
c_edge[index].weight = -1;
/*更新我们的c_edge数组。*/
edge * temp = g.list[c_edge[index].end].edge1;
while (temp) {
if (c_edge[temp->toppoint].weight > temp->weight) {
c_edge[temp->toppoint].weight = temp->weight;
c_edge[temp->toppoint].start = index;
c_edge[temp->toppoint].end = temp->toppoint;
}
temp = temp->next1;
}
}
printf("%d\n",w);
}
int main()
{
creatGraph(g1);
print(g1);
prime(g1,1);
cout << "Hello world!" << endl;
return 0;
}