Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 12777 | Accepted: 6547 |
Description
Input
Output
Sample Input
2 A: B: 4 A:BC B:ACD C:ABD D:BC 4 A:BCD B:ACD C:ABD D:ABC 0
Sample Output
1 channel needed. 3 channels needed. 4 channels needed.
传送门:题解
此题极其特别,因为是平面图,我们可以利用它的对偶图的面着色来处理,由于四色猜想已被计算机证明(尽管很多数学家不承认,但结论确实是对的),如果你也投靠那些不承认的数学家,那也没有问题,五色定理是已经被证明的,因此可以利用这个来剪枝,其实剪不剪复杂度都是O(n^2),但是对于n很大时,剪枝要快得多,这里数据量较小,就不剪枝了,剪枝也很方便,改几处代码就可以了,留给你们思考。
代码(未剪枝):
#include<cstdio> #include<iostream> #include<cstring> #define Maxn 30 using namespace std; char s[Maxn]; int adj[Maxn][Maxn]; int vis[Maxn],color[Maxn]; int dye(int n){ //染色范围[0,n-1] int ans=-1; memset(color,-1,sizeof color); for(int i=0;i<n;i++){ memset(vis,0,sizeof vis); for(int j=0;j<n;j++) if(adj[i][j]&&color[j]!=-1) vis[color[j]]=1; for(int j=0;j<n;j++) if(!vis[j]){ color[i]=j; ans=max(ans,j); break; } } return ans+1; } int main() { int n; while(cin>>n,n){ memset(adj,0,sizeof adj); for(int i=0;i<n;i++){ cin>>s; for(int j=2;s[j];j++) adj[i][s[j]-'A']=adj[s[j]-'A'][i]=1; } int ans=dye(n); if(ans==1) printf("1 channel needed.\n"); else printf("%d channels needed.\n",ans); } return 0; }
特别补上:
poj数据太弱!
这题没那么容易,上面的解法是错误的,特此纠正,顺序染色得到的不一定是最优解。
错误样例:
5
A:D
B:C
C:BDE
D:AC
E:C
正解应该是2,程序跑出来是3.
还有一种解法就是dfs贪心染色,这种做法我也写了程序,poj上反而WA了,说来奇怪,貌似该方法看上去是对的。但还是不要想当然,可以负责任地告诉你,贪心思想也是错的,得到的也不一定是最优解。
错误样例:
6
A:BEF
B:AC
C:BD
D:CEF
E:ADF
F:ADE
正解应该是3,程序跑出来是4.
正确的要怎么做?要我说就是纯暴力(把所有情况都试探一下),当然利用四色定理将复杂度优化下来,我优化到了O(3^n)。
正确的代码:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define Maxn 30 using namespace std; char s[Maxn]; int adj[Maxn][Maxn]; int color[Maxn]; int n; int ans; bool check(int u,int c){ for(int v=0;v<u;v++) if(adj[u][v]&&color[v]==c) return false; return true; } void dfs(int d){ if(d==n){ ans=min(ans,*max_element(color,color+n)); return; } for(int c=1;c<4;c++) if(check(d,c)){ color[d]=c; dfs(d+1); } } void solve(){ color[0]=1; ans=4; dfs(1); } int main() { while(cin>>n,n){ memset(adj,0,sizeof adj); for(int i=0;i<n;i++){ cin>>s; for(int j=2;s[j];j++) adj[i][s[j]-'A']=adj[s[j]-'A'][i]=1; } solve(); if(ans==1) printf("1 channel needed.\n"); else printf("%d channels needed.\n",ans); } return 0; }