BZOJ 1997: [Hnoi2010]Planar|2-SAT|二分图染色
2016-01-07 09:05
351 查看
一道比较奇怪的题
用二分图染色和2-SAT都可以建模
想了一下为什么
二分图染色是找出矛盾的关系连边
2-SAT是找出“必须”的关系连边
而此题恰好都满足
--------------------------------------------------
2-SAT做法:
一组边a,b在环构成的圆内相交 那么在圆外的a‘,b'也相交
”必须“关系有 a-->b' a'-->b b-->a b'-->a
直接连边就可以了然后tarjan判断
--------------------------------------------------
二分图染色做法:
引用上面的a,b,a',b'
矛盾关系就是 a-->a' b-->b' a-->b a'-->b'
两种算法的复杂度是一样的然后用二分图染色的话,常数会稍小点
下面贴代码
2-SAT 124ms
二分图染色 100ms
用二分图染色和2-SAT都可以建模
想了一下为什么
二分图染色是找出矛盾的关系连边
2-SAT是找出“必须”的关系连边
而此题恰好都满足
--------------------------------------------------
2-SAT做法:
一组边a,b在环构成的圆内相交 那么在圆外的a‘,b'也相交
”必须“关系有 a-->b' a'-->b b-->a b'-->a
直接连边就可以了然后tarjan判断
--------------------------------------------------
二分图染色做法:
引用上面的a,b,a',b'
矛盾关系就是 a-->a' b-->b' a-->b a'-->b'
两种算法的复杂度是一样的然后用二分图染色的话,常数会稍小点
下面贴代码
2-SAT 124ms
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<set> #include<map> #include<algorithm> #include<iostream> using namespace std; int sc() { int i=0; char c=getchar(); while( c>'9' || c<'0' ) c=getchar(); while( c>='0'&& c<='9') i=i*10+c-'0',c=getchar(); return i; } int u[11111],v[11111]; int head[1888],nxt[1222222],lst[1222222]; int dfn[1888],low[1888],st[1888],vis[1888],bl[1888]; int num[222],pos[222]; int n,m,total,tot,cnt,scc,top; void insert(int x,int y) { lst[++tot]=y; nxt[tot]=head[x]; head[x]=tot; } void tarjan(int x) { vis[x]=1; st[++top]=x; dfn[x]=low[x]=++cnt; for(int i=head[x]; i; i=nxt[i]) { if(vis[lst[i]]) low[x]=min(low[x],dfn[lst[i]]); else if(!dfn[lst[i]]) { tarjan(lst[i]); low[x]=min(low[x],low[lst[i]]); } } if(dfn[x]==low[x]) { int k=0; scc++; while(k!=x) { k=st[top--]; bl[k]=scc; vis[k]=0; } } } int main() { int Q=sc(); while(Q--) { memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); int flag=0; total=tot=cnt=top=scc=0; n=sc(); m=sc(); for(int i=1; i<=m; i++) u[i]=sc(),v[i]=sc(); for(int i=1; i<=n; i++) num[i]=sc(),pos[num[i]]=i; if(m>3*n-6) {puts("NO");continue;} for(int i=1; i<=m; i++) { u[i]=pos[u[i]],v[i]=pos[v[i]]; if(u[i]>v[i]) swap(u[i],v[i]); if(v[i]-u[i]==1||v[i]-u[i]==n-1) continue; u[++total]=u[i],v[total]=v[i]; } for(int i=1; i<=total; i++) for(int j=i+1; j<=total; j++) if((u[i]<u[j]&&u[j]<v[i]&&v[i]<v[j])||(u[j]<u[i]&&u[i]<v[j]&&v[j]<v[i])) { insert(2*i,2*j+1); insert(2*i+1,2*j); insert(2*j,2*i+1); insert(2*j+1,2*i); } for(int i=2; i<=2*total+1; i++) if(!dfn[i]) tarjan(i); for(int i=1; i<=total; i++) if(bl[i*2]==bl[i*2+1]){flag=1,puts("NO");break;} if(!flag) puts("YES"); } return 0; }
二分图染色 100ms
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<queue> #include<vector> #include<set> #include<map> #include<algorithm> #include<iostream> using namespace std; int sc() { int i=0; char c=getchar(); while( c>'9' || c<'0' ) c=getchar(); while( c>='0'&& c<='9') i=i*10+c-'0',c=getchar(); return i; } int u[11111],v[11111]; int head[1888],nxt[1222222],lst[1222222]; int col[1888]; int num[222],pos[222]; int n,m,total,tot; void insert(int x,int y) { lst[++tot]=y; nxt[tot]=head[x]; head[x]=tot; } bool color(int x,int f) { col[x]=f; for(int i=head[x]; i; i=nxt[i]) { if(!col[lst[i]]) { if(!color(lst[i],f^1)) return 0; } else if(col[lst[i]]==col[x]) return 0; } return 1; } int main() { int Q=sc(); while(Q--) { memset(head,0,sizeof(head)); memset(col,0,sizeof(col)); int flag=0; total=tot=0; n=sc(); m=sc(); for(int i=1; i<=m; i++) u[i]=sc(),v[i]=sc(); for(int i=1; i<=n; i++) num[i]=sc(),pos[num[i]]=i; if(m>3*n-6) {puts("NO");continue;} for(int i=1; i<=m; i++) { u[i]=pos[u[i]],v[i]=pos[v[i]]; if(u[i]>v[i]) swap(u[i],v[i]); if(v[i]-u[i]==1||v[i]-u[i]==n-1) continue; u[++total]=u[i],v[total]=v[i]; } for(int i=1; i<=total; i++) for(int j=i+1; j<=total; j++) if((u[i]<u[j]&&u[j]<v[i]&&v[i]<v[j])||(u[j]<u[i]&&u[i]<v[j]&&v[j]<v[i])) { insert(2*i,2*j); insert(2*j,2*i); insert(2*i+1,2*j+1); insert(2*j+1,2*i+1); } for(int i=1; i<=total; i++) insert(2*i,2*i+1),insert(2*i+1,2*i); for(int i=2; i<=total*2+1; i++) if(!col[i]&&!color(i,2)){flag=1;break;} if(flag)puts("NO");else puts("YES"); } return 0; }
相关文章推荐
- oracle查询优化,存储过程select表循环插入另一个表,以及索引重建
- java160104MakeNameDemo
- StreamCQL源码阅读(4) 应用程序执行
- [王垠系列]什么是“对用户友好”
- 详解iOS应用UI开发中的九宫格坐标计算与字典转换模型
- 8 个你可能不知道的 Docker 知识
- 【LEETCODE】11-Container With Most Water [Python]
- java160104JinZhiDemo
- StreamCQL源码阅读(3) 拆分组合算子
- 关于 C# 调用 JavaWebservice服务,版本不一致的问题
- 第一组咖啡机器人界面设计1月6日进展
- 编程之美 - 买书问题
- 初步入NDK(Jni)开发遇到的问题错误
- java160104KeyWordDemo
- moc文件的作用
- StreamCQL源码阅读(2) 语法和语义解析
- Andorid中.9.png图片不失真的调试和制作
- zabbix监控esxi主机
- 从 GMM 到 EM 算法
- jQuery中判断一个元素是否为另一个元素的子元素(或者其本身)