洛谷P2819图的m着色问题, POJ 1129 Channel Allocation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
#include <cstdio> using namespace std; const int MAXN = 1E3; bool gra[MAXN][MAXN] = {false}; int color[MAXN] = {0};
int n, k, m, e1, e2, ans = 0;
bool check(int num) { for(int i = 1; i <= num; i++) { if(gra[i][num] == true && color[i] == color[num]) return false; } return true; }
void dfs(int num) { if(num > n) { ans++; return; } for(int i = 1; i <= m; i++) { color[num] = i; if(check(num)) dfs(num+1); else color[num] = 0; } } int main() { scanf("%d %d %d", &n, &k, &m); for(int i = 1; i <= k; i++) { scanf("%d %d", &e1, &e2); gra[e1][e2] = true; gra[e2][e1] = true; } dfs(1); printf("%d\n", ans); return 0; }
|
题目
解析
参考:https://blog.csdn.net/lyy289065406/article/details/6647986
题意:
当一个广播电台在一个非常大的地区,广播站会用中继器来转播信号以使得每一个接收器都能接收到一个强烈的信号。然而,每个中继器必须慎重选择使用,使相邻的中继器不互相干扰。如果相邻的中继器使用不同的频道,那么就不会相互干扰。
由于无线电频道是一有限的,一个给定的网络所需的中继频道数目应减至最低。编写一个程序,读取一个中继网络,然后求出需要的最低的不同频道数。
即一个有N个节点的无向图,要求对每个节点进行染色,使得相邻两个节点颜色都不同,问最少需要多少种颜色?
暴力搜索
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
#include <cstdio> #include <cstring> using namespace std; const int MAXN = 1E3; bool gra[MAXN][MAXN] = {false}; int color[MAXN] = {0};
int n, ans = 0; bool Find = false;
bool check(int num) { for(int i = 0; i < num; i++) { if(gra[i][num] == true && color[i] == color[num]) return false; } return true; }
void dfs(int num, int cnt) { if(Find) return; if(num >= n) { Find = true; return; } for(int i = 1; i <= cnt; i++) {
color[num] = i; if(check(num)) dfs(num+1, cnt); else color[num] = 0; } if(!Find) { ans++; dfs(num, cnt+1); } }
int main() { char s[MAXN]; while(scanf("%d", &n) != EOF && n) { getchar(); memset(gra, false, sizeof(gra)); memset(color, 0, sizeof(color)); for(int i = 0; i < n; i++) { scanf("%s", s); int e1 = s[0]-'A'; for(int j = 2; s[j] != '\0'; j++) { int e2 = s[j]-'A'; gra[e1][e2] = gra[e2][e1] = true; } } ans = 1; Find = false; dfs(0,1); if (ans == 1) printf ("1 channel needed.\n"); else printf ("%d channels needed.\n", ans); } return 0; }
|
四色定理剪枝
四色问题的内容是:任何一张地图只用四种颜色就能使具有共同边界的国家着上不同的颜色。”也就是说在不引起混淆的情况下一张地图只需四种颜色来标记就行。
四色定理的“相邻”是指两块多边形地区“至少一条边重合”才为之相邻
“至少一条边重合”同时也隐含了“任意边(线段)不正规相交
本题的相邻是“两点有边连接,但任意两边不交叉(正规相交)”,这种“相邻”其实就是四色定理的“相邻”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| #include <cstdio> #include <cstring> using namespace std; const int MAXN = 1E3; bool gra[MAXN][MAXN] = {false}; int color[MAXN] = {0};
int n, ans = 0; bool Find = false;
bool check(int num) { for(int i = 0; i < num; i++) { if(gra[i][num] == true && color[i] == color[num]) return false; } return true; }
void dfs(int num, int cnt) {
if(Find) return; if(num >= n) { Find = true; return; } for(int i = 1; i <= cnt; i++) {
color[num] = i; if(check(num)) dfs(num+1, cnt); else color[num] = 0; } if(!Find) { ans++; if(cnt+1 == 4) { ans = 4; return; } else dfs(num, cnt+1); } }
int main() { char s[MAXN]; while(scanf("%d", &n) != EOF && n) { getchar(); memset(gra, false, sizeof(gra)); memset(color, 0, sizeof(color)); for(int i = 0; i < n; i++) { scanf("%s", s); int e1 = s[0]-'A'; for(int j = 2; s[j] != '\0'; j++) { int e2 = s[j]-'A'; gra[e1][e2] = gra[e2][e1] = true; } } ans = 1; Find = false; dfs(0,1); if (ans == 1) printf ("1 channel needed.\n"); else printf ("%d channels needed.\n", ans); } return 0; }
|
题目
解析
此题是一道经典的图的染色问题,等同于:对图经行染色,且相邻的顶点不能染同样的颜色,问至少需要多少种不同的颜色
参考:https://www.cnblogs.com/looeyWei/p/10439834.html
https://blog.csdn.net/memeda1141/article/details/80301201
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #include <cstdio> const int MAXN = 1E3; bool gra[MAXN][MAXN] = {false}; int room[MAXN][MAXN] = {0}; int room_num[MAXN] = {0};
int n, m, e1, e2, ans = 1e9;
void dfs(int num, int cnt) { if(cnt >= ans) return; if(num > n) { if(ans > cnt) ans = cnt; return; } for(int i = 1; i <= cnt; i++) { int len = room_num[i]; int k = 0; for(int j = 1; j <= len; j++) { if(!gra[num][room[i][j]]) k++; } if(k == len) { room[i][++room_num[i]] = num; dfs(num+1, cnt); room_num[i]--; } } room[cnt+1][++room_num[cnt+1]] = num; dfs(num+1, cnt+1); room_num[cnt+1]--; } int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= m; i++) { scanf("%d%d", &e1, &e2); gra[e1][e2] = gra[e2][e1] = true; } dfs(1, 0); printf("%d", ans); return 0; }
|