暴力输出图的指定定点数的所有完全子图

在求无向图的完全子图之前,先看另一个算法问题
在n个顶点中顶点数(顶点用 1,2,3,4,5 . . . n 表示),输出指定定点数k并且顶点值和等于m的顶点集,结果用二进制串表示。如:
n= 6,k= 3, m= 8时满足有三个顶点,并且三个顶点和为8的有{1,3,4},{1,2,5}
则输出101100 110010。
暴力遍历:


#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
int n, k, m, b[100];

//输出
void PrintBinaryString()
{
	for (int i = 1; i <= n; i++)
	{
		printf("%d", b[i]);
	}
	printf(" ");
}

void GenStrings(int t, int d, int sum) 
{
	if (t > n) 
	{ 
	   if(m==sum)
	           PrintBinaryString();
	}
	else 
	{
		// Still room to add 0s
		if(n-t+1 > k-d) 
		{
			b[t] = 0;
			GenStrings(t+1, d, sum);}
		// Still room to add 1s
		if(d < k) 
		{
			b[t] = 1;
			GenStrings(t+1, d+1, sum+t);
		}
	}
}

int main() { 
    scanf("%d %d %d", &n, &m, &k);
	for (int i = 0; i < m; i++)
	{
		scanf("%d %d", &graph[i][0], &graph[i][1]);
	}
	GenStrings(1,0,0);
} 

GenStrings(int t,int d,int sum)中,t是记录数组b[]当前操作位置的索引,d是记录数组b[]中1的个数(即顶点个数)遇到满足d=k,sum=m时输出b[]中前n个数即所求。递归遍历从000…1(n位) 到111…1(n位)的所有情况。

基于这个问题,只需把判断if(m=sum)改为if(此刻的数组b中记录的顶点之间都有边)即可,这无疑增加了很多复杂度,大佬看看就好,勿喷。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
int n, k, m, b[100], graph[100][2];

//判断两个顶点之间是否有边
int VerifySingle(int v1, int v2)
{
	for (int i = 0; i < m; i++)
	{
		if (graph[i][0] == v1 && graph[i][1] == v2)
		{
			return 1;
		}
	}
	return 0;
}
//判断所有顶点之间是否都有边
int VerifyMultiple()
{	
	for (int i = 1; i <= n; i++)
	{
		if (b[i] == 1)
		{
			for (int j = i + 1; j <= n; j++)
			{
				if (b[j] == 1)
				{
					if (VerifySingle(i, j) == 0)
						return 0;
				}
			}
		}
	}
	return 1;
}

void PrintBinaryString()
{
	for (int i = 1; i <= n; i++)
	{
		printf("%d", b[i]);
	}
	printf(" ");
}

void GenStrings(int t, int d) 
{
	if (t > n) 
	{ 
		if (VerifyMultiple() == 1)
		{
			PrintBinaryString();
		}
	}
	else 
	{
		// Still room to add 0s
		if(n-t+1 > k-d) 
		{
			b[t] = 0;
			GenStrings(t+1, d);}
		// Still room to add 1s
		if(d < k) 
		{
			b[t] = 1;
			GenStrings(t+1, d+1);
		}
	}
}
//加载图
void LoadGraph(char *filename)
{
	FILE *fRead = fopen(filename, "r");
	if (fRead == NULL)
	{
		return;
	}
	fscanf(fRead, "%d %d %d\n", &n, &m, &k);
	for (int i = 0; i < m; i++)
	{
		fscanf(fRead, "%d %d\n", &graph[i][0], &graph[i][1]);
	}
}

//输入图
void InputGraph()
{
	scanf("%d %d %d", &n, &m, &k);
	for (int i = 0; i < m; i++)
	{
		scanf("%d %d", &graph[i][0], &graph[i][1]);
	}
}

int main() { 
	clock_t start, finish;
	double time;
	LoadGraph("F:\\g3.txt");
	start = clock();
	GenStrings(1, 0);
	finish = clock();
	time = ((double)(finish - start) / CLOCKS_PER_SEC);
	printf("%0.8f seconds", time);
	getchar();
} 

注意,输入边时,必须按照边的左顶点递增,左顶点相同时右顶点递增的顺序。
给出一个Example:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值