链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4488
题意:
输入一个n(3≤n≤9999)个点m条边(2≤m≤100000)的连通图,n保证为奇数。
设k为最小的奇数,使得每个点的度数不超过k,你的任务是把图中的结点涂上颜色1~k,使得相邻结点的颜色不同。
多解时输出任意解。输入保证有解。
分析:
递归构造可以解决这道题。不过为什么可以这样我还没想明白。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 using namespace std; 5 6 const int UP = 9999 + 5; 7 int k, vis[UP], color[UP]; 8 vector<int> edge[UP]; 9 10 void dfs(int node){ 11 if(color[node]) return; 12 for(int i = 0; i < edge[node].size(); i++){ 13 int b = edge[node][i]; 14 vis[color[b]] = node; 15 } 16 for(int i = 1; i <= k; i++) if(vis[i] != node){ 17 color[node] = i; 18 break; 19 } 20 for(int i = 0; i < edge[node].size(); i++) dfs(edge[node][i]); 21 } 22 23 int main(){ 24 int n, m; 25 while(~scanf("%d%d", &n, &m)){ 26 for(int i = 1; i <= n; i++) edge[i].clear(); 27 for(int f, b, i = 0; i < m; i++){ 28 scanf("%d%d", &f, &b); 29 edge[f].push_back(b); 30 edge[b].push_back(f); 31 } 32 33 k = 0; 34 for(int i = 1; i <= n; i++) k = max(k, (int)edge[i].size()); 35 if(k % 2 == 0) k++; 36 37 memset(vis, 0, sizeof(vis)); 38 memset(color, 0, sizeof(color)); 39 dfs(1); 40 41 printf("%d ", k); 42 for(int i = 1; i <= n; i++) printf("%d ", color[i]); 43 printf(" "); 44 } 45 return 0; 46 }