如何求一个图的连通性加权图

问题陈述:给定一个连通图G=(V,E),如下图所示,求它的连通性图。
算法:
输入:一个连通图G=(V,E)
输出:输出G的连通性图Gc=(V,E,sc(u,v))
k=1;
while(求解k边连通分量非空)do
求解k边连通分量,将其内包含的边的权值改为k;
k=k+1;
end while;

输入输出用到的图我都是用邻接矩阵也就是一个二维数组来存储的。
因为我毕设要做的算法是在属性图上的,所以展示的图是带有属性的,大家看的时候把属性忽略就好啦。
在这里插入图片描述

代码如下所示:

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#include <algorithm>
using namespace std;
const int INF = 1000000;
const int N  = 110;
int side[N][N];
int sc[N][N];
int grid[N][N];
int w[N];
bool vis[N];
bool deleted[N];
bool choose[N];
int K;
 //定义了两个队列qa,qb 
queue<int>qa,qb;
//定义了两个向量qc和qd用来记录属性得分最大的图内包含的节点 
vector<int>qc,qd;
vector<int>VQuery;
vector<char>AQuery;					
vector<char>attribute[14];
int pointsum1=0; //qc的得分 
int pointsum2=0;//qd的得分 
						
vector<int>nodes[N];
//设查询节点为1,6,查询属性集为{music,art}


//prim算法求两点之间的最小割 
int prim(int k,int n,int &s,int &t){	//求k和n点之间的最小割 
	s=0;                                //s=0 第0个顶点 
	while(deleted[s])s++;               //若deleted[s]=True时候,s++ 
	for(int i=0;i<n;i++){               //遍历n次 
		w[i]=grid[s][i];                //w记录了与s点相连的点 
		vis[i]=false;                   //vis中的n个元素全部为false 
	}
	vis[s]=true;                        //第s个 顶点位置置为true 
	int p;                              //定义一个顶点p,一个最大值Max 
	int Max;                           
	for(int i=1;i<k;i++){               
		Max=-INF;						//Max=-INF 
		for(int j=0;j<n;j++)			//遍历n次 
			if(!vis[j]&&!deleted[j]){   //vis【j】假且deleted【j】假 
				if(w[j]>Max){			//如果w【j】>Max 
					Max=w[j];			//则Max=W【j】 
					p=j;				//p=j 
			}
		}
		if(i==k-2)s=p;
		if(i==k-1)t=p;
		vis[p]=true;
		for(int i=0;i<n;i++)			//遍历n次 
			if(!vis[i]&&!deleted[i]){	//vis【j】假且deleted【j】假 
				w[i]+=grid[i][p];       //w[i]=w[i]+grid[i][p]
		}
	}
	return w[t];                         //w[t]记录了最小割 
}
//求全局最小割 
int stoerwagner(int n){
	if(n<=1)return 0;        //如果节点数小于等于1,则返回0 
	int min_cut=INF,s,t;     // 
	for(int i=0;i<n;i++){    //将deleted全赋值为false,nodes={0,1,2,3,4} 
		deleted[i]=false;
		nodes[i].clear();
		nodes[i].push_back(i);
	}
	for(int i=1;i<n;i++){                //  遍历n-1次就可以找到全局最小割了 
		int cut=prim(n-i+1,n,s,t);       // 求割边cut是prim(n-i+1,n,s,t) 
		if(cut<min_cut){				  
			min_cut=cut;
			for(int j=0;j<n;j++)      
				choose[j]=0;             
			for(int j=0;j<nodes[t].size();j++)
				choose[nodes[t][j]]=1;    
		}
		for(int i=0;i<nodes[t].size();i++){
			nodes[s].push_back(nodes[t][i]);
		}
		deleted[t]=true;
		for(int i=0;i<n;i++){
			if(i==s)continue;
			if(!deleted[i]){
				grid[s][i]+=grid[t][i];
				grid[i][s]+=grid[i][t];
			}
		}
	}
	for(int i=0;i<n;i++){
		if(choose[i])qa.push(i);      //把节点集合分成两部分 
		else qb.push(i);
	}
	return min_cut;
}
//solve递归解决问题 求连通度图 
int solve(vector<int> a){					  
	int n=a.size();                           
	if(n<=1)return 1;                         //如果节点个数小于等于1则返回1 
	int t;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++){
		grid[i][j]=side[a[i]][a[j]];           // 将side赋值给grid 
	}
	if(stoerwagner(n)==K){   
		//求连通度图
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++){
				sc[a[i]][a[j]]=side[a[i]][a[j]]*K;
			}
		while(!qa.empty())qa.pop();            // 若qa非空,qa出队 
		while(!qb.empty())qb.pop();            // 若qb非空,qb出队 
		return 1;
	}
	vector<int>x,y;                            //定义两个向量x和y 
	while(!qa.empty()){                        //当qa非空时候 
		x.push_back(a[qa.front()]);
		qa.pop();    						   //将 
	}
	while(!qb.empty()){
		y.push_back(a[qb.front()]);
		qb.pop();};
	return solve(x)+solve(y);
}
//solve1求k边连通分量 
int solve1(vector<int> a){					  //a={0,1,2,3,4} 
	int n=a.size();                           //n是节点的个数 n=5 
	if(n<=1)return 1;                         //如果节点个数小于等于1则返回1 
	int t;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++){
		grid[i][j]=side[a[i]][a[j]];           // 将side赋值给grid 
	}
	if(stoerwagner(n)==K){   
	             
		while(!qa.empty())qa.pop();            // 若qa非空,qa出队 
		while(!qb.empty())qb.pop();            // 若qb非空,qb出队 
		return 1;
	}
	vector<int>x,y;                            //定义两个向量x和y 
	while(!qa.empty()){                        //当qa非空时候 
		x.push_back(a[qa.front()]);
		qa.pop();    						   //将 
	}
	while(!qb.empty()){
		y.push_back(a[qb.front()]);
		qb.pop();};
	return solve1(x)+solve1(y);
}
int main(){
	int n,m;
	K=1;
	n=14;
	m=29;
	//memset(side,0,sizeof(side));
VQuery.push_back(0);
VQuery.push_back(5);
AQuery.push_back('music');
AQuery.push_back('art');
attribute[0].push_back('film');
attribute[0].push_back('music');
attribute[1].push_back('film');
attribute[1].push_back('music');
attribute[2].push_back('film');
attribute[2].push_back('music');
attribute[3].push_back('film');
attribute[3].push_back('music');
attribute[4].push_back('film');
attribute[5].push_back('music');
attribute[5].push_back('art');
attribute[6].push_back('music');
attribute[7].push_back('music');
attribute[7].push_back('art');
attribute[8].push_back('music');
attribute[8].push_back('art');
attribute[9].push_back('art');
attribute[10].push_back('art');
attribute[10].push_back('sport');
attribute[11].push_back('art');
attribute[12].push_back('art');
attribute[13].push_back('music');
attribute[13].push_back('art');
attribute[13].push_back('sport');
	side[0][1]=1;
	side[1][0]=1;
	side[0][2]=1;
	side[2][0]=1;
	side[0][3]=1;
	side[3][0]=1;
	side[0][4]=1;
	side[4][0]=1;
	side[1][2]=1;
	side[2][1]=1;
	side[1][3]=1;
	side[3][1]=1;
	side[1][4]=1;
	side[4][1]=1;
	side[2][3]=1;
	side[3][2]=1;
	side[2][4]=1;
	side[4][2]=1;
	side[3][4]=1;
	side[4][3]=1;
	side[3][4]=1;
	side[3][6]=1;
	side[6][3]=1;
	side[4][6]=1;
	side[6][4]=1;
	side[4][8]=1;
	side[8][4]=1;
	side[4][11]=1;
	side[11][4]=1;
	side[6][5]=1;
	side[5][6]=1;
	side[6][7]=1;
	side[7][6]=1;
	side[6][8]=1;
	side[8][6]=1;
	side[5][8]=1;
	side[8][5]=1;
	side[5][7]=1;
	side[7][5]=1;
	side[7][8]=1;
	side[8][7]=1;
	side[8][9]=1;
	side[9][8]=1;
	side[8][10]=1;
	side[10][8]=1;
	side[10][13]=1;
	side[13][10]=1;
	side[9][10]=1;
	side[10][9]=1;
	side[9][11]=1;
	side[11][9]=1;
	side[11][12]=1;
	side[12][11]=1;
	side[10][12]=1;
	side[12][10]=1;
	side[9][12]=1;
	side[12][9]=1;
	side[10][11]=1;
	side[11][10]=1;
	
		vector<int>graph;
		for(int i=0;i<n;i++){
			graph.push_back(i);
		}
		//求连通性图 
		int ab=solve(graph);
		while(ab<14){
			K=K+1;
			ab=solve(graph);		
		}
		printf("连通度图为:\n");
		for(int i=0;i<14;i++){
			for(int j=0;j<14;j++)
			{
				printf("%d ",sc[i][j]);
			}
			printf("\n");
		}
	}

运行结果就是这样啦,可以看到连通性图求解是正确的。
在这里插入图片描述
因为我在学习的过程中特别希望有人已经写过这个算法了(hhh毕竟copy真的很香),所以我就把我写的分享一下,希望能够给在学习图搜索的童鞋一些帮助吧。
后续也可能会在这里继续分享一些相关的算法,也算是自己的一个学习笔记了。
如果有错误的地方,也欢迎指正呀。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值