顶点覆盖,最大团
最小权顶点覆盖问题
给 定一个赋权无向图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; }