最大团问题
来源:互联网 发布:南山软件产业基地图片 编辑:程序博客网 时间:2024/06/06 05:50
百度上的定义:
http://baike.baidu.com/item/%E6%9C%80%E5%A4%A7%E5%9B%A2%E9%97%AE%E9%A2%98
简单的讲最大团就是最大完全子图
一般做法就是dfs+剪枝
可参考这篇博客:
http://www.cnblogs.com/zhj5chengfeng/p/3224092.html
下面介绍几个例题:
1、第一道裸题:ZOJ 1492 Maximum Clique
给了一个最多包含 50 个点的无向图,让求这个图中最大团所包含的的点的数量
直接套模板就行。。
#include <set>#include <map>#include <queue>#include <vector>#include <math.h>#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;#define ff first#define ss second#define pb push_back#define ll long long#define mod 1000000007#define ull unsigned long long#define mst(ss,b) memset(ss,b,sizeof(ss));#define pl(x) cout << #x << "= " << x << endl;const int inf = 0x3f3f3f3f;const int N = 1e5+5;struct node{ static const int N = 60; //可修改 bool G[N][N]; //初始化 int n, Max[N], Alt[N][N], ans; bool dfs(int cur, int tol){ if(cur == 0){ if(tol>ans){ // 用一个更大的极大团替代原有的极大团 ans = tol; return 1; } return 0; } for(int i=0; i<cur; i++){ if(cur-i+tol <= ans)return 0; int u = Alt[tol][i]; if(Max[u]+tol <= ans)return 0; int nxt = 0; for(int j=i+1; j<cur; j++) if(G[u][Alt[tol][j]])Alt[tol+1][nxt++] = Alt[tol][j]; if(dfs(nxt, tol+1)) return 1; } return 0; } int max_clique(){ ans = 0; mst(Max, 0); for(int i=n-1; i>=0; i--){ // 先找一个点,把与它相连的点加进来,这些点可能构成最大团,然后dfs判断出一个临时极大团 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; }};node mc;int main(){ while(~scanf("%d", &mc.n)){ if(!mc.n)break; for(int i=0; i<mc.n; i++) for(int j=0; j<mc.n; j++) scanf("%d", &mc.G[i][j]); //G[u][v]表示u,v之间是否有边 printf("%d\n", mc.max_clique()); } return 0;}
2.一般无向图最大独立集的题目:POJ 1419 Graph Coloring
给了一个有 n 个点 m 条边的无向图,要求用黑、白两种色给图中顶点涂色,相邻的两个顶点不能涂成黑色,求最多能有多少顶点涂成黑色。图中最多有 100 个点
从相邻的点不能够涂上相同的颜色我们可以得出该题的实质就是要求一个最大的点独立集,而求一个图的点独立集如果所给的图是一棵树的话,就可以通过拆点转化为二分图来解了,由于给定的图很可能成环,因此化作二分图的做法在这里不再适应。另一个对应的问题就是通过对原图建一个反图,然后对反图做一个最大团的求解,最大团保证了是反图中的最大完全子集,任何两个元素之间都有边相连,反应在原图中则是任意两两之间不存在边,也就是两两不相邻,这刚好契合的题意。
ps:这题需要记录顶点
#include <set>#include <map>#include <stack>#include <queue>#include <string>#include <vector>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <string.h>#include <algorithm>using namespace std;#define ff first#define ss second#define pb push_back#define ll long long#define mod 1000000007#define ull unsigned long long#define mst(ss,b) memset(ss,b,sizeof(ss));#define pl(x) cout << #x << "= " << x << endl;const int inf = 0x3f3f3f3f;const int N = 1e5+5;// **** 表示记录顶点的部分struct node{ static const int N = 105; //可修改 bool G[N][N]; // 点标号从0开始 Ķ int n, Max[N], Alt[N][N], ans; int tmp[N], ret[N]; // **** bool dfs(int cur, int tol){ if(cur == 0){ if(tol>ans){ memcpy(ret, tmp, sizeof tmp); // **** 用一个更大的极大团替代原有的极大团 ans = tol; return 1; } return 0; } for(int i=0; i<cur; i++){ if(cur-i+tol <= ans)return 0; int u = Alt[tol][i]; if(Max[u]+tol <= ans)return 0; int nxt = 0; for(int j=i+1; j<cur; j++) if(G[u][Alt[tol][j]])Alt[tol+1][nxt++] = Alt[tol][j]; tmp[tol+1] = u;// **** if(dfs(nxt, tol+1)) return 1; } return 0; } int max_clique(){ ans = 0; mst(Max, 0); 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; }};node mc;int main(){ int T, m; scanf("%d", &T); while(T--){ mst(mc.G, true); scanf("%d%d", &mc.n, &m); for(int i=1; i<=m; i++){ int u, v; scanf("%d%d", &u, &v); mc.G[u-1][v-1] = mc.G[v-1][u-1] = 0; } int ans = mc.max_clique(); printf("%d\n", ans); for(int i=1; i<=ans; i++){ printf("%d%c", mc.ret[i]+1, i==ans?'\n':' '); //注意输出标号是否+1 } } return 0;}
3.一道经典的染色问题:POJ 1129 Channel Allocation
最多 26 广播电台…我还是讲抽象之后的题意吧:最多26个点的无向图,要求相邻的节点不能染成同一个颜色,问最少需要多少颜色染完所有的顶点
利用上面提到的结论:图的染色问题中,最少需要的颜色的数量=最大团点的数量,建图,跑最大团即可
直接爆搜,理论复杂度是O(n*n*m)
#include <set>#include <map>#include <queue>#include <vector>#include <math.h>#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;#define ff first#define ss second#define pb push_back#define ll long long#define mod 1000000007#define ull unsigned long long#define mst(ss,b) memset(ss,b,sizeof(ss));#define pl(x) cout << #x << "= " << x << endl;const int inf = 0x3f3f3f3f;const int N = 25;int n, m;bool mp[N][N], fg;int col[N];void dfs(int x, int tol){//当前点 最大色彩数 if(fg)return ; if(x == n+1){ fg = 1; return ; } for(int i=1; i<=min(x, tol); i++){ col[x] = i; bool ok = 1; for(int j=1; j<x; j++){ if(mp[x][j] && col[x] == col[j]){ ok = 0; break; } } if(ok)dfs(x+1, tol); }}char s[30];int main(){ while(~scanf("%d", &n), n){ mst(mp, 0); for(int i=1; i<=n; i++){ scanf("%s", s); for(int j=2; s[j]; j++) mp[s[0]-'A'+1][s[j]-'A'+1] = 1; } fg = 0; for(int i=1; i<=n; i++){ dfs(1, i); if(fg){ if(i == 1)printf ("1 channel needed.\n"); else printf ("%d channels needed.\n", i); break; } } } return 0;}
以下代码作废:
#include <set>#include <map>#include <stack>#include <queue>#include <string>#include <vector>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <string.h>#include <algorithm>using namespace std;#define ff first#define ss second#define pb push_back#define ll long long#define mod 1000000007#define ull unsigned long long#define mst(ss,b) memset(ss,b,sizeof(ss));#define pl(x) cout << #x << "= " << x << endl;const int inf = 0x3f3f3f3f;const int N = 1e5+5;struct node{ static const int N = 27; bool G[N][N]; int n, Max[N], Alt[N][N], ans; bool dfs(int cur, int tol){ if(cur == 0){ if(tol>ans){ ans = tol; return 1; } return 0; } for(int i=0; i<cur; i++){ if(cur-i+tol <= ans)return 0; int u = Alt[tol][i]; if(Max[u]+tol <= ans)return 0; int nxt = 0; for(int j=i+1; j<cur; j++) if(G[u][Alt[tol][j]])Alt[tol+1][nxt++] = Alt[tol][j]; if(dfs(nxt, tol+1)) return 1; } return 0; } int max_clique(){ ans = 0; mst(Max, 0); 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; }};node mc;int main(){ while(~scanf("%d", &mc.n), mc.n){ char s[30]; mst(mc.G, 0); for(int i=1; i<=mc.n; i++){ scanf("%s", s); for(int j=2; s[j]; j++){ int u = s[0] - 'A', v = s[j] - 'A'; mc.G[u][v] = 1; } } int ans = mc.max_clique(); if(ans == 1)printf("%d channel needed.\n", ans); else printf("%d channels needed.\n", ans); } return 0;}
- 最大团问题
- 最大团问题 MCP
- 最大团问题
- 最大团问题
- 最大团问题
- 最大团问题转载
- 最大团问题
- 最大团问题
- 最大团问题
- 最大团问题
- 最大团问题
- 最大团问题
- 最大团问题
- POJ 1419 最大团问题
- hdu 5277(最大团问题)
- Maximum Clique最大团问题
- 关于最大团问题,解zju1492
- 最大团问题-分支限界算法
- Linux入门学习教程:虚拟机体验之KVM篇
- 最大熵模型maxent及icwb2-data评估用法
- 简单改进的快排算法——含代码
- [机器学习]机器学习笔记整理02-机器学习概述
- Android中几个常用的工具类总结
- 最大团问题
- 参考学习目录
- JMS之——ActiveMQ的安装和启动
- 八数码问题
- Ubuntu16.04 mysql 编码方式配置
- 设置Service为前台服务,保证service不会被杀死!!
- python中pandas库学习笔记
- 五位运动员问题的优化
- java xml SAX解析