概述
讲解就在这里http://www.cnblogs.com/zhj5chengfeng/archive/2013/07/29/3224092.html
说的很清晰,列举的题目也比较简单
重要的几个结论
1、最大团点的数量=补图中最大独立集点的数量
2、二分图中,最大独立集点的数量+最小覆盖点的数量=整个图点的数量
3、二分图中,最小覆盖点的数量=最大匹配的数量
4、图的染色问题中,最少需要的颜色的数量=最大团点的数量
模板
ZOJ 1492 MAXClique
给了一个最多包含 50 个点的无向图,让求这个图中最大团所包含的的点的数量
直接按照上面所讲的 DFS 过程做就行
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL unsigned long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);} const int MAXN = 70; struct Max_Clique { int G[MAXN][MAXN]; int N,MAX[MAXN],Alt[MAXN][MAXN],ans; bool dfs(int cur,int tot) { if (cur == 0) { if (tot > ans) { ans = tot; return true; } return false; } for (int i = 0 ; i < cur ; i++) { if (cur - i + tot <= ans) return false; int u = Alt[tot][i]; if (MAX[u] + tot <= ans) return false; int nxt = 0; for (int j = i + 1 ; j < cur ; j++) if (G[u][Alt[tot][j]]) Alt[tot + 1][nxt++] = Alt[tot][j]; if (dfs(nxt,tot + 1)) return true; } return false; } int MaxClique() { ans = 0; memset(MAX,0,sizeof(MAX)); for (int i = N - 1 ; i >= 0 ; i--) { int cur = 0; for (int j = i + 1 ; j < N ; j++) { if (G[i][j]) Alt[1][cur++] = j; } dfs(cur,1); MAX[i] = ans; } return ans; } }slover; int main() { while (scanf("%d",&slover.N) != EOF) { if (slover.N == 0) break; for (int i = 0 ; i < slover.N ; i++) for (int j = 0 ; j < slover.N ; j++) scanf("%d",&slover.G[i][j]); printf("%dn",slover.MaxClique()); } return 0; }
POJ 3692 Kindergarten
二分图中补图的最大独立集==最大团
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 410; bool used[MAXN]; int linker[MAXN]; int g[MAXN][MAXN]; int G,B,M; bool dfs(int u) { for (int i = 1 ; i <= B ; i++) { if (g[u][i] == 0 && !used[i]) { used[i] = true; if (linker[i] == -1 || dfs(linker[i])) { linker[i] = u; return true; } } } return false; } int calcu() { int ret = 0; memset(linker,-1,sizeof(linker)); for (int i = 1 ; i <= G ; i++) { memset(used,false,sizeof(used)); if (dfs(i)) ret++; } return ret; } int main() { int kase = 1; while (scanf("%d%d%d",&G,&B,&M) != EOF) { if (G == 0 && B == 0 && M == 0) break; memset(g,0,sizeof(g)); while (M--) { int u,v; scanf("%d%d",&u,&v); g[u][v] = 1; } printf("Case %d: ",kase++); printf("%dn",G + B - calcu()); } return 0; }
HDU 3585 maximum shortest distance
给了平面上 n 个点,要求选出 k 个点来,使得这 k 个点中,距离最近的两个点的距离最大。n 最大为50
二分距离大于距离建图求最短就行了
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL unsigned long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);} const int MAXN = 70; const double eps = 1e-3; const double INF = 1e15; struct Max_Clique { int G[MAXN][MAXN]; int N,MAX[MAXN],Alt[MAXN][MAXN],ans; bool dfs(int cur,int tot) { if (cur == 0) { if (tot > ans) { ans = tot; return true; } return false; } for (int i = 0 ; i < cur ; i++) { if (cur - i + tot <= ans) return false; int u = Alt[tot][i]; if (MAX[u] + tot <= ans) return false; int nxt = 0; for (int j = i + 1 ; j < cur ; j++) if (G[u][Alt[tot][j]]) Alt[tot + 1][nxt++] = Alt[tot][j]; if (dfs(nxt,tot + 1)) return true; } return false; } int MaxClique() { ans = 0; memset(MAX,0,sizeof(MAX)); for (int i = N - 1 ; i >= 0 ; i--) { int cur = 0; for (int j = i + 1 ; j < N ; j++) { if (G[i][j]) Alt[1][cur++] = j; } dfs(cur,1); MAX[i] = ans; } return ans; } }slover; struct point { double x,y; }src[MAXN]; int N,K; double dis(point a,point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } bool judge(double mid) { memset(slover.G,0,sizeof(slover.G)); for (int i = 0 ; i < N ; i++) for (int j = i + 1 ; j < N ; j++) { double dist = dis(src[i],src[j]); if (dist >= mid) slover.G[i][j] = slover.G[j][i] = 1; } int num = slover.MaxClique(); if(num >= K)return true; return false; } int main() { while (scanf("%d%d",&N,&K) != EOF) { for (int i = 0 ; i < N ; i++)scanf("%lf%lf",&src[i].x,&src[i].y); slover.N = N; double L = 0,R = 500000.0; for (int i = 1 ; i <= 50 ; i++) { double mid = (L + R) / 2.0; if (judge(mid)) L = mid; else R = mid; } printf("%.2lfn",L); } return 0; }
POJ 1419 Graph Coloring
给了一个有 n 个点 m 条边的无向图,要求用黑、白两种色给图中顶点涂色,相邻的两个顶点不能涂成黑色,求最多能有多少顶点涂成黑色。图中最多有 100 个点
利用结论补图最大独立集等于最大团
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL unsigned long long #define PI 3.1415926535897932626 typedef long long type; using namespace std; type gcd(type a, type b) {return b == 0 ? a : gcd(b, a % b);} const int MAXN = 110; struct Max_Clique { int G[MAXN][MAXN]; int N,MAX[MAXN],Alt[MAXN][MAXN],ans; int ret[MAXN],tot1; int tmp[MAXN],tot2; void init(int n) { N = n; } bool dfs(int cur,int tot) { if (cur == 0) { if (tot > ans) { ans = tot; for (int i = 1 ; i <= tot ; i++) { ret[i] = tmp[i]; } return true; } return false; } for (int i = 0 ; i < cur ; i++) { if (cur - i + tot <= ans) return false; int u = Alt[tot][i]; if (MAX[u] + tot <= ans) return false; int nxt = 0; for (int j = i + 1 ; j < cur ; j++) if (G[u][Alt[tot][j]]) Alt[tot + 1][nxt++] = Alt[tot][j]; tmp[tot + 1] = u; if (dfs(nxt,tot + 1)) return true; } return false; } int MaxClique() { ans = 0; memset(MAX,0,sizeof(MAX)); for (int i = N - 1 ; i >= 0 ; i--) { int cur = 0; tmp[1] = i; for (int j = i + 1 ; j < N ; j++) { if (G[i][j]) Alt[1][cur++] = j; } dfs(cur,1); MAX[i] = ans; } return ans; } }slover; int main() { int T; scanf("%d",&T); while (T--) { int N,M; scanf("%d%d",&N,&M); slover.init(N); for (int i = 0 ; i <= N ; i++) for (int j = 0 ; j <= N ; j++) slover.G[i][j] = 1; for (int i = 0 ; i < M ; i++) { int u,v; scanf("%d%d",&u,&v); u--; v--; slover.G[u][v] = 0; slover.G[v][u] = 0; } int res = slover.MaxClique(); printf("%dn",res); for (int i = 1 ; i <= res ; i++) { printf("%d%c",slover.ret[i] + 1,i == res ? 'n' : ' '); } } return 0; }
POJ 1129 Channel Allocation
最多26个点的无向图,要求相邻的节点不能染成同一个颜色,问最少需要多少颜色染完所有的顶点
利用结论:最少需要的颜色的数量=最大团点的数量
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL unsigned long long #define PI 3.1415926535897932626 typedef long long type; using namespace std; type gcd(type a, type b) {return b == 0 ? a : gcd(b, a % b);} const int MAXN = 110; struct Max_Clique { int G[MAXN][MAXN]; int N,MAX[MAXN],Alt[MAXN][MAXN],ans; void init(int n) { N = n; } bool dfs(int cur,int tot) { if (cur == 0) { if (tot > ans) { ans = tot; return true; } return false; } for (int i = 0 ; i < cur ; i++) { if (cur - i + tot <= ans) return false; int u = Alt[tot][i]; if (MAX[u] + tot <= ans) return false; int nxt = 0; for (int j = i + 1 ; j < cur ; j++) if (G[u][Alt[tot][j]]) Alt[tot + 1][nxt++] = Alt[tot][j]; if (dfs(nxt,tot + 1)) return true; } return false; } int MaxClique() { ans = 0; memset(MAX,0,sizeof(MAX)); for (int i = N - 1 ; i >= 0 ; i--) { int cur = 0; for (int j = i + 1 ; j < N ; j++) { if (G[i][j]) Alt[1][cur++] = j; } dfs(cur,1); MAX[i] = ans; } return ans; } }slover; int main() { int N; while (scanf("%d",&N) != EOF) { if (N == 0) break; slover.init(N); char str[5010]; memset(slover.G,0,sizeof(slover.G)); for (int i = 0 ; i < N ; i++) { scanf("%s",str); int len = strlen(str); for (int j = 2 ; j < len ; j++) { int id = str[j] - 'A'; slover.G[i][id] = slover.G[id][i] = true; } } int ret = slover.MaxClique(); if (ret == 1) printf("1 channel needed.n"); else printf("%d channels needed. n", ret); } return 0; }
转载于:https://www.cnblogs.com/Commence/p/4945575.html
最后
以上就是无奈戒指为你收集整理的最大团问题的全部内容,希望文章能够帮你解决最大团问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复