链接:http://poj.org/problem?id=1129
题意:当一个广播站向一个很广的地区广播时需要使用中继器,用来转发信号,使得接收器都能收到足够强的信号。然后,每个中继器所使用的频道必须很好的选择,以保证相邻的中继器不会互相干扰。要满足这个条件,相邻中继器必须使用不同的频道。但是频道是很宝贵的,对于一个中继器网络,所使用的频道应当尽量少,现在告诉你中继网络信息,求最少需要使用多少个频道。
思路:根据题目建图,把中继器看做点,有边相连的两个点应当使用不同的频道,所以这是一个平面图顶点着色问题,这类问题并没有有效的算法,顺序着色法用贪心的思想:在给任何一个点着色时,采用其邻接顶点中没有使用的编号最小的颜色
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0) #define MAXN 30 #define eps 1e-7 #define INF 0x3F3F3F3F //0x7FFFFFFF #define LLINF 0x7FFFFFFFFFFFFFFF #define seed 1313131 #define MOD 1000000007 #define ll long long #define ull unsigned ll #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct node{ int u, v, next; }edge[MAXN * MAXN]; int head[MAXN], cnt, n; int ans, v_color[MAXN]; //顶点着色数,各顶点的颜色 int color_use[MAXN]; //每种颜色使用的标识,等于1表示这种颜色已使用 void add_edge(int u, int v){ edge[cnt].u = u; edge[cnt].v = v; edge[cnt].next = head[u]; head[u] = cnt++; } void greedy(){ int i, k; for(i = 1; i <= n; i++){ //给第i个顶点着色 memset(color_use, 0, sizeof(color_use)); for(k = head[i]; k != -1; k = edge[k].next){ int v = edge[k].v; if(v_color[v] != -1) //邻接顶点v已着色,颜色为v_color[v] color_use[v_color[v]] = 1; } for(k = 1; k <= i; k++){ //k为i的所有邻接顶点中没有使用的编号最小的颜色,编号从1开始 if(!color_use[k]) break; } v_color[i] = k; //给当前顶点上色 } for(i = 1; i <= n; i++){ if(ans < v_color[i]) ans = v_color[i]; } } int main(){ int i, j; char str[500]; while(scanf("%d", &n), n){ cnt = 0; memset(head, -1, sizeof(head)); for(i = 0; i < n; i++){ scanf("%s", str); int u = str[0] - 'A' + 1; int l = strlen(str); for(j = 2; j < l; j++){ int v = str[j] - 'A' + 1; add_edge(u, v); } } ans = 0; memset(v_color, -1, sizeof(v_color)); greedy(); if(ans == 1) puts("1 channel needed."); else printf("%d channels needed.\n", ans); } return 0; }
时间: 2024-10-26 13:18:47