在求无向图的完全子图之前,先看另一个算法问题
在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: