图的色数问题整理(未完待续......)
来源:互联网 发布:linux基础与大作业 编辑:程序博客网 时间:2024/05/16 11:32
最近离散在讲图的色数问题,顺便做了几道题。前面两道题代码主要参考刘汝佳的紫书的dp。后面一题为cf上的求三个链节点的图的色数(前面只是两个相邻节点),用dfs或者bfs遍历全图实现。具体下面分析。
先是poj的1129,可以说是两个邻接点的图的色数的裸题。数组讲道理应该开到1<<26那么大,但是会mle,后来本着试一试的态度把它改成了1<<20竟然过了。。。只能说数据有点水,或者实际上计算机只能处理到20位这么多??这道题另一个思路是用四色定理,也是网上大部分的解题思路,回头研究一下。
代码:
#include<cstdio>#include<cstring>#include<vector>#include<algorithm>#include<iostream>#define INF 0x3f3f3f3fusing namespace std;const int maxn=100;const int maxs=1<<20;char s[maxn],st,g;int n,d[maxs],nums[maxn],cnt;bool no_edge_inside(int id,vector<int> edge[]){ for(int i=1;i<=n;i++) if(id&(1<<(i-1))){///找到id内的所有子集 for(int j=0;j<edge[i].size();j++) if((1<<(edge[i][j]-1))&id)///在id的子集i中找它的邻接点,如果同样也是id的子集,则说明这个子集内部有边。 return false; } return true;}///no_edge_inside函数的另一种写法(g[i][j]存图,有边则为1,反之为0):/*bool no_inside_edge(int s0){ vector<int> si; for(int i=1;i<=n;i++) if(s0&(1<<(i-1))) si.push_back(i);//把子集的点先存入si中 for(int i=0;i<si.size();i++) for(int j=i+1;j<si.size();j++){//再在si中找看看两两间是否有边相连。 if(g[si[i]][si[j]]) return false; } return true;}*/void solve(vector<int> edge[]){ d[0]=0; for(int S=1;S<(1<<n);S++){ d[S]=INF; for(int S0=S;S0;S0=(S0-1)&S){ if(no_edge_inside(S0,edge)) d[S]=min(d[S],d[S-S0]+1); } }}int main(){ while(scanf("%d",&n)!=EOF){ vector<int> edge[maxn]; memset(nums,0,sizeof(nums)); memset(d,0,sizeof(d)); memset(s,0,sizeof(s)); cnt=0; if(n==0) break; for(int i=1;i<=n;i++){ scanf("%s",s); if(nums[s[0]]==0) nums[s[0]]=++cnt; int c=nums[s[0]];///对应字母的编号 for(int i=2;i<strlen(s);i++){ if(nums[s[i]]==0) {nums[s[i]]=++cnt;} edge[c].push_back(nums[s[i]]); } } solve(edge); if(d[(1<<n)-1]==1) printf("%d channel needed.\n",d[(1<<n)-1]); else printf("%d channels needed.\n",d[(1<<n)-1]);///注意这里有坑 } return 0;}
CodeForces - 782C
题目给你一个无环图,问至少要用多少种颜色涂这个图,使得同一链节上的三个相邻的节点颜色不同。这道题是不能用上面的思路解决的。主要是三个节点两两间没有边相连,不一定就可以涂上相同的颜色。只能用搜索解决。然后这里面有个取巧的地方在于最多的颜色为max(点的度数)+1;然后只需要设置一个数组color来记录当前节点颜色与父亲节点,爷爷节点,以及同父母兄弟节点不同不同就可以了。
dfs
#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<iostream>using namespace std;const int maxn=3e5+50;//太大,cb上运行会报错。。。int n,st,ed,c,fcolor[maxn],color[maxn],deg,no;void dfs(int f,int u,int c1,int c2,vector<int> v[]){///f:当前点的父节点编号,u当前点编号,c1:color[f],c2:color[u] int cc=1;///cc记录为即将访问点的颜色编号 for(int i=0;i<v[u].size();i++){ if(v[u][i]==f) continue; if(color[v[u][i]]) continue; for(;cc<=deg;cc++){///遍历找到与父爷不同的颜色。 if(c1!=cc&&c2!=cc){///因为dfs是在for循环里进行,所以返回后cc是接着下来,所以同父子节点的编号是不同的 no=v[u][i]; color[no]=cc; break; } } cc++;///这里记得加加,break后没有+1 dfs(u,no,color[u],color[no],v);}}int main(){ while(scanf("%d",&n)!=EOF){ vector<int> v[maxn]; memset(color,0,sizeof(color)); deg=0; c=2; for(int i=0;i<n-1;i++){ scanf("%d%d",&st,&ed); v[st].push_back(ed); v[ed].push_back(st); } for(int i=1;i<=n;i++){ int temp=v[i].size(); deg=max(deg,temp+1); }///计算最小色数 for(int i=0;i<v[1].size();i++){ color[1]=1; color[v[1][i]]=c++; dfs(1,v[1][i], color[1],color[v[1][i]],v); } printf("%d\n",deg); for(int i=1;i<=n;i++) printf("%d%c",color[i],i==n?'\n':' '); } return 0;}bfs:
思路基本上上面一样,不同的是要多设置fa,fcolor数组记录节点的父亲编号和父亲的颜色。
#include<cstdio>#include<queue>#include<cstring>#include<vector>#include<algorithm>using namespace std;const int maxn=2e5+50;int color[maxn],fcolor[maxn],n,st,ed,fa[maxn],cc,deg;void bfs(int st,vector<int> v[]){ queue<int> q; color[st]=1; fa[st]=fcolor[st]=-1; q.push(st); while(!q.empty()){ int no=q.front(); q.pop(); cc=1; for(int i=0;i<v[no].size();i++){ int temp=v[no][i]; if(color[temp]) continue; if(temp==fa[no]) continue; q.push(temp); fa[temp]=no; fcolor[temp]=color[no]; for(;cc<=deg;cc++){ if(cc!=fcolor[temp]&&cc!=fcolor[no]){ color[temp]=cc; break; } } cc++; } } }int main(){ while(scanf("%d",&n)!=EOF){ vector<int> v[maxn]; memset(color,0,sizeof(color)); memset(fcolor,0,sizeof(fcolor)); memset(fa,0,sizeof(fa)); deg=0; for(int i=0;i<n-1;i++){ scanf("%d%d",&st,&ed); v[st].push_back(ed); v[ed].push_back(st); } for(int i=1;i<=n;i++){ int temp=v[i].size(); deg=max(deg,temp+1); } bfs(1,v); printf("%d\n",deg); for(int i=1;i<=n;i++) printf("%d%c",color[i],i==n?'\n':' '); } return 0;}
阅读全文
0 0
- 图的色数问题整理(未完待续......)
- IE与FireFox的兼容性问题(JoeCom整理--未完待续)
- 关于抽象类的整理(未完待续)
- RMQ问题(未完待续)
- 统计数字问题(未完待续)
- percona-toolkit常用工具整理(未完待续)
- UML整理-未完待续
- 寻找最大回文数(未完待续)
- 安装GT4时遇到的一些问题(未完待续)
- 仙人掌相关问题的处理方法(未完待续)
- 关于Mysql的死锁问题(未完待续)
- magento 常用函数整理了(未完待续,长期整理)
- 2.内核模块问题(未完待续)
- WebSphere问题集锦(未完待续)
- 背包问题总结(未完待续)
- 常用JS整理,未完待续~
- 常用JS整理,未完待续~
- 整理一下常用的Linux命令(1)(未完待续)
- Nginx配置详解
- 作业4--线性表类型定义与顺序表操作
- PATCH
- 简单的MS COCO数据集下载方法
- 字符数组内容逆序输出
- 图的色数问题整理(未完待续......)
- 环海陆港分析国际外汇黄金最新消息
- Apache 配置访问日志
- JVM 内存结构图
- .NET日常之枚举
- 如何保证kafka 的消息机制
- 高精地图--资料整理
- 记MyBatis和MySQL中遇到的一些小问题
- 自然语言处理-NLP应用分类