很容易超时的,会更新
#include<stdio.h>
#include<vector>
#include<stdlib.h>
#include<algorithm>
using namespace std;
//需要以上头文件
class MST//图的邻接表类
{
private:
typedef struct EDGE {
int x, y, weight;
EDGE(int a, int b, int c) :weight(c), x(a), y(b) {}
EDGE() :weight(), x(), y() {}
bool operator <(const EDGE& b)
const {
if (weight == b.weight)
if (x == b.x) {
return y < b.y;
}
else return x < b.x;
else
return weight < b.weight;
}
}edge;//边类
typedef struct POINT{
int x, y, weight;
struct POINT* next;
POINT() :weight(), x(), y(), next() {}
POINT(int a, int b, int c, POINT* next) :weight(c), x(a), y(b), next(next) {}
}point;//点类
vector<point*> Point;//点集
vector<int> per;//并查集
vector<edge> Edge;//边集
point* PointCreat()//分配点的内存
{
point* s = (point*)malloc(sizeof(point));
s->next = NULL;
return s;
}
void PointBuilt(int n)//0到n点初始化
{
for(int i=0;i<=n;i++){
point *s=PointCreat();
*s=point(0,0,0,NULL);
Point.push_back(s);
}
}
void PointClear(int n)//0到n点清空
{
point *tt;
for (int i = 0; i <= n; i++){
tt=Point[i];
listClear(tt);
Point[i]=PointCreat();
*Point[i]=point(0,0,0,NULL);
}
}
void listClear(point* x)//清空辅助
{
if (x == NULL) return;
if (x->next != NULL) {
listClear(x->next);
}
free(x);
}
void UnionBuilt(int n)//0到n并查集初始化
{
for (int i = 0; i <= n; i++) {
per.push_back(i);
}
}
void UnionClear(int n)//0到n并查集清空
{
per.clear();
}
void UnionConnect(int x, int y)//把x所在集合连到y
{
x = Find(x);
y = Find(y);
if (x != y){
per[x] = y;
}
}
public:
void Minimum_spanning_tree(){
sort(Edge.begin(), Edge.end());
while (!Edge.empty()){
if (Find(Edge[0].x) != Find(Edge[0].y))
{
PointConnect(Edge[0].x, Edge[0].y, Edge[0].weight, 1);
}
Edge.erase(Edge.begin());
}
}
void built(int n)//初始化n阶图
{
UnionBuilt(n);
PointBuilt(n);
Edge.clear();
weight=0;
}
void Edgepush(int x, int y, int q)//输入边
{
Edge.push_back(edge(x, y, q));
}
void clear(int n)//清空n阶图
{
PointClear(n);
UnionClear(n);
Edge.clear();
}
int Find(int x)//并查集用
{
if (per[x] != x) x = Find(per[x]);
else return x;
return x;
}
int weight;
void PointConnect(int from, int to, int weight, int mode)//根据边集连接点,mode=1有向
{
UnionConnect(from,to);
point* s = PointCreat();
point* t = Point[from];
*s = point(from, to, weight, t->next);
t->next = s;
if (mode)PointConnect(to, from, weight, 0);
}
void getweight(int before, int now)
{
point* K = Point[now];
if (K == NULL) return;
K = K->next;
while (K != NULL){
if (K->y != before){
weight += K->weight;
getweight(now, K->y);
}
K = K->next;
}
}
};
外部接口
Minimum_spanning_tree() //生成最小生成树。
built(int n) //初始化(赋予内存)//没新建就使用一定有bug。
clear(int n) //清空所有(释放内存)//释放完要再新建。
Edgepush(int x, int y, int q) //输入边。
Find(int x) //连通分支查找,同连通分支返回值相同。
PointConnect(int from, int to, int weight, int mode)//根据边集连接点mode=1有向,mode=0无向。//图类外部接口,其实求生成树的时候没有用
getweight(0,0)//求树的权重/
int weight;//权重。
2021/5/29
数组版本来了,速度会更快。
删除了built方法,宏定义了点和边的最大个数,并且更新了求最小生成树中两点中的花费方法。
2021/5/30
修改了Minimum_spanning_tree(),增加了对能否生成最小生成树的判断。
修改了clear方法,现在从clear输入边和点的个数,其他方法都不用带上点或边的个数了。
将边数设为外部接口,方便临时修改。
新增 bool isUniqueMST()方法,判断最小生成树是否唯一。
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
using namespace std;
#define MaximumOfPoint 1000
#define MaximumOfEdge 100005
class MAP//图的邻接表类
{
private:
typedef struct EDGE{
int x, y, weight;
bool use;
EDGE(int a, int b, int c) :weight(c), x(a), y(b),use(false) {}
EDGE() :weight(), x(), y(),use() {}
bool operator <(const EDGE& b)
const {
if (weight == b.weight)
if (x == b.x){
return y < b.y;
}
else return x < b.x;
else
return weight < b.weight;
}
}edge;//边类
typedef struct POINT{
int x, y, weight;
struct POINT* next;
POINT() :weight(), x(), y(), next() {}
POINT(int a, int b, int c, POINT* next) :weight(c), x(a), y(b), next(next) {}
}point;//点类
point* Point[MaximumOfPoint];//点集
int per[MaximumOfPoint];//并查集
point* PointCreat(){
point* s = (point*)malloc(sizeof(point));
s->next = NULL;
return s;
}//分配点的内存
int Unionsum;
void PointClear(){
point* tt;
for (int i = 0; i <= Pointsum; i++){
tt = Point[i];
listClear(tt);
Point[i] = PointCreat();
*Point[i] = point(0, 0, 0, NULL);
}
}//0到n点清空
void listClear(point* x){
if (x == NULL) return;
if (x->next != NULL){
listClear(x->next);
}free(x);
}//清空辅助
void UnionConnect(int x, int y){
x = Find(x);
y = Find(y);
if (x != y){
per[x] = y;
Unionsum--;
}
}//把x所在集合连到y
int getCost(int aim,int before,int now,int i){
point* K = Point[now];
if (K == NULL ) return 0;
if (now == aim) return 1;
K = K->next;
while (K != NULL){
if (K->y != before){
if(getCost(aim,now,K->y,i)){
maxCost=max(maxCost,K->weight);
minCost=min(minCost,K->weight);
totalCost+=K->weight;
return 1;
}
}K = K->next;
}
}
void getWeight(int before, int now,int i){
point* K = Point[now];
if (K == NULL) return;
K = K->next;
while (K != NULL){
if (K->y != before){
Weight += K->weight;
getWeight(now, K->y,i);
}
K = K->next;
}
}
int Pointsum;
public:
int Edgesum;
int Weight;
edge Edge[MaximumOfEdge];//边集
bool Minimum_spanning_tree(){
sort(Edge, Edge + Edgesum);
int i = 0;
while (i < Edgesum){
if (Find(Edge[i].x) != Find(Edge[i].y)){
PointConnect(Edge[i].x, Edge[i].y, Edge[i].weight, 1);
Weight += Edge[i].weight;
Edge[i].use=true;
}i++;
}
return (Unionsum==1)?true:false;//若不能生成返回false
}
bool isUniqueMST(){
for(int i=0;i<Edgesum;i++){
if(Edge[i].use==false){
getCost(Edge[i].x,Edge[i].y);
if(maxCost>=Edge[i].weight) return false;
}
}
return true;
}
void clear(int n,int m){//
Pointsum=n;Edgesum=m;Unionsum=n;
memset(Edge,0,sizeof(Edge));
for (int i = 0; i <= Pointsum; i++){
Weight = 0;maxCost=0;totalCost=0;minCost=0;
point* tt;
per[i] = i;
tt = Point[i];
listClear(tt);
Point[i] = PointCreat();
*Point[i] = point(0, 0, 0, NULL);
}
}//清空n阶图
int Find(int x){
int tt =x;
while(x!=per[x]) x=per[x];
while(tt!=x){
int t=per[tt];
per[tt]=x;
tt=t;
}
return x;
}//并查集用
void PointConnect(int from, int to, int weight, int mode){
UnionConnect(from,to);
point* s = PointCreat();
point* t = Point[from];
*s = point(from, to, weight, t->next);
t->next = s;
if (mode)PointConnect(to, from, weight, 0);
}//根据边集连接点,mode=1有向
void Edgepush(int x, int y, int q,int i){
Edge[i]=(edge(x, y, q));
}
void getWeight(int now){
Weight=0;
getWeight(now,now,1);
}
int totalCost;
int maxCost;
int minCost;
int getCost(int from,int aim){
totalCost=0;
maxCost=0;
minCost=2147483647;//MAXINT
getCost(aim,from,from,1);
}
};
外部接口
没写返回值都默认是void
bool Minimum_spanning_tree() //生成最小生成树(Kruskal算法)//能生成返回true不能false。
clear(int n,int m) //清空 n个点和所有边
Edgepush(int x, int y, int q,int i) //输入边。
int Find(int x) //连通分支查找,同连通分支返回值相同//图类外部接口,其实求生成树的时候没有用
PointConnect(int from, int to, int weight, int mode) //根据边集连接点mode=1有向,mode=0无向。 //图类外部接口,其实求生成树的时候没有用
getWeight(int now)//求树的权重 //保证now 是图中一点
getCost(int from,int aim) //得到图中从from到aim的点的总花费,最大最小花费
bool isUniqueMST() //判断最小生成树是否唯一//唯一true//不唯一false
int Weight;//权重。
int totalCost; //总花费
int maxCost;int minCost; //最大最小花费
int Edgesum//边数
2021/12/1
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
using namespace std;
#define MaximumOfPoint 1000
#define MaximumOfEdge 100005
class MAP//图的邻接表类
{
private:
typedef struct EDGE{
int x, y, weight;
bool use;
EDGE(int a, int b, int c) :weight(c), x(a), y(b),use(false) {}
EDGE() :weight(), x(), y(),use() {}
bool operator <(const EDGE& b)
const {
if (weight == b.weight)
if (x == b.x){
return y < b.y;
}
else return x < b.x;
else
return weight < b.weight;
}
}edge;//边类
typedef struct POINT{
int x, y, weight;
struct POINT* next;
POINT() :weight(), x(), y(), next() {}
POINT(int a, int b, int c, POINT* next) :weight(c), x(a), y(b), next(next) {}
}point;//点类
point* Point[MaximumOfPoint];//点集
int per[MaximumOfPoint];//并查集
point* PointCreat(){
point* s = (point*)malloc(sizeof(point));
s->next = NULL;
return s;
}//分配点的内存
int Unionsum;
void PointClear(){
point* tt;
for (int i = 0; i <= Pointsum; i++){
tt = Point[i];
listClear(tt);
Point[i] = PointCreat();
*Point[i] = point(0, 0, 0, NULL);
}
}//0到n点清空
void listClear(point* x){
if (x == NULL) return;
if (x->next != NULL){
listClear(x->next);
}free(x);
}//清空辅助
void UnionConnect(int x, int y){//并查集用
x = Find(x);
y = Find(y);
if (x != y){
per[x] = y;
Unionsum--;
}
}//把x所在集合连到y
int getCost(int aim,int before,int now,int i){//获得aim到before 的费用
point* K = Point[now];
if (K == NULL ) return 0;
if (now == aim) return 1;
K = K->next;
while (K != NULL){
if (K->y != before){
if(getCost(aim,now,K->y,i)){
maxCost=max(maxCost,K->weight);
minCost=min(minCost,K->weight);
totalCost+=K->weight;
return 1;
}
}K = K->next;
}
}
int Pointsum;
void PointConnect(int from, int to, int weight,int i){
UnionConnect(from,to);
point* s = PointCreat();
point* t = Point[from];
*s = point(from, to, weight, t->next);
t->next = s;
if (i)PointConnect(to, from, weight,0);//
}//根据边集连接点,mode=1有向
void getWeight(int before, int now,int i){
Weight=0;
point* K = Point[now];
if (K == NULL) return;
K = K->next;
while (K != NULL){
if (K->y != before){
Weight += K->weight;
getWeight(now, K->y,i);
}
K = K->next;
}
}
void printree(int before,int now,int deep)
{
point *K=Point[now];
K=K->next;
if(K==NULL) return;
{
while(K!=NULL){
if(K->y!=before){int n=deep;
while(n--)
{
printf("-");
}
printf("%d\n",K->y);
printree(now,K->y,deep*2);
}
K=K->next;
}
}
}
public:
int Edgesum;
int mode;
int Weight;
edge Edge[MaximumOfEdge];//边集
bool built_Minimum_spanning_tree(int true_is_directed){
mode=true_is_directed;
sort(Edge, Edge + Edgesum);
int i = 0;
while (i < Edgesum){//这是Kruskal算法
if (Find(Edge[i].x) != Find(Edge[i].y)){//用并查集判断两个点是否在同一个集合
PointConnect(Edge[i].x, Edge[i].y, Edge[i].weight,1);//连接两个点,在
Weight += Edge[i].weight;
Edge[i].use=true;
}i++;
}
return (Unionsum==1)?true:false;//若不能生成返回false
}
bool isUniqueMST(){//最小生成树是否唯一
for(int i=0;i<Edgesum;i++){
if(Edge[i].use==false){
getCost(Edge[i].x,Edge[i].y);
if(maxCost>=Edge[i].weight) return false;
}
}
return true;
}
void GetMap(int n){//
Pointsum=n;Edgesum=0;Unionsum=n;
memset(Edge,0,sizeof(Edge));
for (int i = 0; i <= Pointsum; i++){
Weight = 0;maxCost=0;totalCost=0;minCost=0;
point* tt;
per[i] = i;
tt = Point[i];
listClear(tt);
Point[i] = PointCreat();
*Point[i] = point(0, 0, 0, NULL);
}
}//清空n阶图
int Find(int x){
int tt =x;
while(x!=per[x]) x=per[x];
while(tt!=x){
int t=per[tt];
per[tt]=x;
tt=t;
}
return x;
}//并查集用
void Edgepush(int x, int y, int q){
Edge[Edgesum++]=(edge(x, y, q));
}
void getWeight(int now){//获取权重
Weight=0;
getWeight(now,now,1);
}
void printree()
{
printf("0\n");//只从编号为0的点输出,树是孩子兄弟链结构
printree(0,0,1);
}
int totalCost;
int maxCost;
int minCost;
int getCost(int from,int aim){
totalCost=0;
maxCost=0;
minCost=2147483647;//MAXINT
getCost(aim,from,from,1);
}
};//图生成后还可以修改
int main()
{
MAP A;
int n,m;
scanf("%d%d",&n,&m);
int x,y,c;
A.GetMap(n);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&c);
A.Edgepush(x,y,c);
}
A.built_Minimum_spanning_tree(1);
printf("其最小生成树为\n");
A.printree();
}
/*
6 8
0 1 9
0 2 10
1 2 7
1 3 5
2 4 6
2 5 7
3 4 11
4 5 8
*/