最小权顶点覆盖问题
给 定一个赋权无向图G=(V,E),每个顶点v∈V都有一个权值w(v)。如果U包含于V,且对于(u,v)∈E 有u∈U 且v∈V-U,则有v∈K.如:U = {1}, 若有边(1,2), 则有2属于K. 若有集合U包含于V使得U + K = V, 就称U 为图G 的一个顶点覆盖。G 的最小权顶点覆盖是指G 中所含顶点权之和最小的顶点覆盖。
输入: 输入数据。第1 行有2 个正整数n 和m,表示给定的图G 有n 个顶点和m条边,顶点编号为1,2,…,n。第2 行有n个正整数表示n个顶点的权。接下来的m行中,每行有2 个正整数u,v,表示图G 的一条边(u,v)。
输出:将计算出的最小权顶点覆盖的顶点权之和输出
#include<iostream>
using namespace std;
int bestw, n, m;
int e[100][100],w[100],c[100];
bool cover()
{
int i=1;
while (i<=n) {
if(c[i] == 1) {
i++;
continue;
}
int t=0;
for(int j=1; j<=n; j++)
if(e[j][i]==1&&c[j]==1&&i!=j) {
t=1;
break;
}
if(t==0)
return false;
i++;
}
return true;
}
void bs(int i,int s)
{
if(s>=bestw)
return;
if(i>n) {
if(cover( ))
bestw=s;
return;
}
c[i]=0;
bs(i+1,s);
c[i]=1;
bs(i+1,s+w[i]);
}
int main()
{
int u,v;
cin >> n >> m;
while( n!=0&&m!=0) {
for(int i=1; i<=n; i++)
cin >> w[i];
memset(c,0,sizeof(int)*n);
memset(e[0],0,sizeof(int)*n*n);
for(int k=1; k<=m; k++) {
cin >> u >> v;
e[u][v]=1;
e[v][u]=1;
}
bestw=100000;
bs(1,0);
cout << bestw << endl;
cin >> n>> m;
}
return 0;
}
最大团问题
给定无向图G=(V, E),其中V是非空集合,称为顶点集;E是V中元素构成的无序二元组的集合,称为边集。如果U∈V,且对任意两个顶点u,v∈U有(u, v)∈E,则称U是G的完全子图。G的完全子图U是G的团当且仅当U不包含在G的更大的完全子图中。G的最大团是指G中所含顶点数最多的团。
//×î´óÍÅÎÊÌâ
#include <iostream>
using namespace std;
int f[30],e[30][30],n,cn=0,bestn,bestf[30];
void backtrack(int i)
{
if(i > n) {
if(cn > bestn){
for(int i=1;i<=n;i++)
bestf[i] = f[i];
bestn = cn;
}
return;
}
bool ok = true;
for(int j=1;j<i && ok;j++)
if(f[j] == 1 && !e[i][j])
ok = false;
if(ok){
f[i] = 1;
cn++;
backtrack(i+1);
cn--;
}
if(cn+n-i>=bestn){// Èç¹ûÖ»ÐèÕÒÒ»¸ö£¬²»ÓÃ=
f[i] = 0;
backtrack(i+1);
}
}
int main()
{
int ne,u,v;
cin >> n >> ne;
memset(f,0,sizeof(int)*n);
memset(e,0,sizeof(int)*n*n);
for(int i=1; i<=ne; i++) {
cin >> u >> v;
e[u][v]=1;
e[v][u]=1;
}
backtrack(1);
for(int i=1;i<=n;i++)
if(bestf[i] == 1)
cout << i << " ";
cout << endl << "max Clique num: "<< bestn << endl;
return 0;
}
