bzoj4025: 二分图
这题想不出来。
不浪费时间了。
以后找时间填。
--------------------update---------------
就是判奇环咯
然而LCT我搞不出来。。
是因为对于当前的最大生成树,新时间加入的边可能是比前面最大生成树里最小边要大,然后就要找到最大生成树里最小的边。。这样要化边为点我萎了还是写不出来你们去%吧
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<map> using namespace std;struct node {int x,y; }a[210000];struct heap_st {int st,ed,id;friend bool operator>(heap_st n1,heap_st n2){return n1.st>n2.st;} };priority_queue<heap_st,vector<heap_st>,greater<heap_st> >A; struct heap_ed {int ed,id;friend bool operator>(heap_ed n1,heap_ed n2){return n1.ed>n2.ed;} };priority_queue<heap_ed,vector<heap_ed>,greater<heap_ed> >B; struct heap_mt {int ed,id;friend bool operator>(heap_mt n1,heap_mt n2){return n1.ed<n2.ed;} };priority_queue<heap_mt,vector<heap_mt>,greater<heap_mt> >C;//---------edge&&heap---------------struct LCT {int f,c,son[2];bool fz; }tr[210000]; void yu(int n){for(int i=1;i<=n;i++)tr[i].c=1,tr[i].fz=false;} void update(int x) {int lc=tr[x].son[0],rc=tr[x].son[1];tr[x].c=tr[lc].c+tr[rc].c+1; } void reverse(int x) {tr[x].fz=false;swap(tr[x].son[0],tr[x].son[1]);int lc=tr[x].son[0],rc=tr[x].son[1];tr[lc].fz=1-tr[lc].fz;tr[rc].fz=1-tr[rc].fz; } void rotate(int x,int w) {int f=tr[x].f,ff=tr[f].f;int R,r;R=f;r=tr[x].son[w];tr[R].son[1-w]=r;if(r!=0)tr[r].f=R;R=ff;r=x;if(tr[R].son[0]==f)tr[R].son[0]=r;else if(tr[R].son[1]==f)tr[R].son[1]=r;tr[r].f=R;R=x;r=f;tr[R].son[w]=r;tr[r].f=R;update(f);update(x); } bool isroot(int x) {if(tr[x].f!=0&&(tr[tr[x].f].son[0]==x||tr[tr[x].f].son[1]==x))return false;return true; } int tmp[210000]; void splay(int x,int rt) {int s=0,i=x;while(isroot(i)==false){tmp[++s]=i;i=tr[i].f;} tmp[++s]=i;while(s!=0){i=tmp[s];s--;if(tr[i].fz==true)reverse(i);}while(isroot(x)==false){int f=tr[x].f,ff=tr[f].f;if(isroot(f)==true){if(x==tr[f].son[0])rotate(x,1);else rotate(x,0);}else{if(tr[f].son[0]==x&&tr[ff].son[0]==f){rotate(f,1);rotate(x,1);}else if(tr[f].son[1]==x&&tr[ff].son[0]==f){rotate(x,0);rotate(x,1);}else if(tr[f].son[0]==x&&tr[ff].son[1]==f){rotate(x,1);rotate(x,0);}else if(tr[f].son[1]==x&&tr[ff].son[1]==f){rotate(f,0);rotate(x,0);}}} }//splayvoid access(int x) {int y=0;while(x!=0){splay(x,0);tr[x].son[1]=y;if(y!=0)tr[y].f=x;update(x);y=x;x=tr[x].f;} } void makeroot(int x) {access(x);splay(x,0);tr[x].fz=1-tr[x].fz; } void Link(int x,int y) {makeroot(x);tr[x].f=y;access(x); } void Cut(int x,int y) {makeroot(x);access(y);splay(y,0);tr[tr[y].son[0]].f=0;tr[y].son[0]=0;update(y); } int findroot(int x) {access(x);splay(x,0);while(tr[x].son[0]!=0)x=tr[x].son[0];return x; }//simpleint getdis(int x,int y) {makeroot(x);access(y);splay(y,0);int ret=1;while(y!=x){y=tr[y].son[0];ret+=tr[tr[y].son[1]].c+1;}return ret; }//-------------------LCT------------------- bool intree[210000];//该边是否在树上 int main() {freopen("data.in","r",stdin);freopen("data.out","w",stdout);int n,m,T;scanf("%d%d%d",&n,&m,&T);yu(n);int st,ed;for(int i=1;i<=m;i++){scanf("%d%d",&a[i].x,&a[i].y);scanf("%d%d",&st,&ed);st++;ed++;if(st>=ed){i--;m--;continue;}heap_st tt;tt.st=st, tt.ed=ed, tt.id=i;A.push(tt);}int tim=0;memset(intree,false,sizeof(intree));for(int t=1;t<=T;t++){while(B.empty()==false){heap_ed h=B.top();if(h.ed==t){B.pop();int k=h.id;if(intree[k]==true){intree[k]=false;Cut(a[k].x,a[k].y);}}else break;}//----------结束时间到,删除树上边,非树上边可以直接无视,更新-------while(A.empty()==false){heap_st h=A.top();if(h.st==t){A.pop();heap_ed tt;tt.ed=h.ed, tt.id=h.id;B.push(tt);heap_mt uu;uu.ed=h.ed, uu.id=h.id;C.push(uu);}else break;}//----------起始时间到,将边入堆---------- while(C.empty()==false){heap_mt h=C.top();C.pop();if(h.ed<=t)break;int k=h.id;int x=a[k].x,y=a[k].y;if(x==y){tim=max(tim,h.ed-1);continue;}if(findroot(x)!=findroot(y)){intree[k]=true;Link(x,y);}else{if(getdis(x,y)%2==1)tim=max(tim,h.ed-1);}}//----------将树边连满&&判奇环---------------- if(t<=tim)printf("No\n");else printf("Yes\n");}return 0; }
lj的WAcode
--------------------然而cdq+带权并查集搞出来了。。。-----------------------
感觉这个不算cdq分治,只是普通分治而已-_-! upd:这个东西其实叫线段树分治。。。。。
具体怎么做呢,就是类似线段树一样把每一时间段下放影响,这样可以保证对于当前这一段包含的边都是没消失的,然后假如遇到奇环就把当前区间全部设为false就行。
dis可以直接用异或代替,因为只是要判奇偶性,路径不用压缩,修改需要父亲,分治可以保证平衡。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> using namespace std;int fa[210000],d[210000]; int findfa(int x) {while(x!=fa[x])x=fa[x];return x; } int getdis(int x) {int dis=0;while(x!=fa[x])dis^=d[x],x=fa[x];return dis; }//---------union-find sets------------- int top,sta[410000];bool v[410000]; int rak[210000]; void Link(int x,int y,int dis) {if(rak[x]>rak[y]){top++;sta[top]=y,v[top]=true;fa[y]=x,d[y]=dis;}else if(rak[x]<rak[y]){top++;sta[top]=x,v[top]=true;fa[x]=y,d[x]=dis;}else{rak[x]++;top++;sta[top]=y,v[top]=false;fa[y]=x,d[y]=dis;} } void Cut(int now) {while(now!=top){int k=sta[top];top--;if(v[top+1]==false)rak[fa[k]]--;fa[k]=k, d[k]=0;} }//------------------玄学-------------------------------- struct edge{int x,y,st,ed;}; bool as[210000]; void cdq(int l,int r,vector<edge> hh) {int mid=(l+r)/2;vector<edge> ll,rr;int len=hh.size(),now=top;for(int i=0;i<len;i++){edge e=hh[i];if(e.st==l&&e.ed==r){int x=e.x,y=e.y;int fx=findfa(x),fy=findfa(y);int dis=getdis(x)^getdis(y)^1;if(fx!=fy)Link(fx,fy,dis);else if((dis&1)>0){for(int i=l;i<=r;i++)as[i]=false;Cut(now);return ;}}else if(e.ed<=mid) ll.push_back(e);else if(mid+1<=e.st)rr.push_back(e);else{edge lc,rc;lc=rc=e;lc.ed=mid;rc.st=mid+1;ll.push_back(lc);rr.push_back(rc);}}if(l==r)as[l]=true;else cdq(l,mid,ll), cdq(mid+1,r,rr);Cut(now); }vector<edge> S; int main() {int n,m,T;scanf("%d%d%d",&n,&m,&T);for(int i=1;i<=m;i++){int x,y,st,ed;scanf("%d%d%d%d",&x,&y,&st,&ed);if(st>=ed)continue;st++; S.push_back((edge){x,y,st,ed});}for(int i=1;i<=n;i++)fa[i]=i;memset(d,0,sizeof(d));memset(rak,0,sizeof(rak));top=0;cdq(1,T,S);for(int i=1;i<=T;i++)if(as[i]==true)printf("Yes\n");else printf("No\n");return 0; }
现在已经看不懂的代码
-------------------------------再一次upd----------------------------------------
学会了线段树分治就是傻子题了,只要上并查集判奇环即可
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> using namespace std;struct edge{int x,y;}e[210000]; struct node {int l,r,lc,rc;vector<int>id,u; }tr[210000];int trlen; void bt(int l,int r) {int now=++trlen;tr[now].l=l;tr[now].r=r;tr[now].lc=tr[now].rc=-1;if(l<r){int mid=(l+r)/2;tr[now].lc=trlen+1;bt(l,mid);tr[now].rc=trlen+1;bt(mid+1,r);} } void insert(int now,int l,int r,int p) {if(tr[now].l==l&&tr[now].r==r){tr[now].id.push_back(p);return ;}int lc=tr[now].lc,rc=tr[now].rc;int mid=(tr[now].l+tr[now].r)/2;if(r<=mid) insert(lc,l,r,p);else if(mid+1<=l)insert(rc,l,r,p);else insert(lc,l,mid,p),insert(rc,mid+1,r,p); }//---------------------------------------init----------------------------------------------------int fa[210000]; const int ot=101000; int findfa(int x) {if(fa[x]<0)return x;return findfa(fa[x]); } void merge(int now,bool &bk,int x,int y) {int fx1=findfa(x),fy2=findfa(y+ot);if(fx1!=fy2){if(fa[fx1]>fa[fy2]){tr[now].u.push_back(fx1);fa[fy2]+=fa[fx1];fa[fx1]=fy2;}else{tr[now].u.push_back(fy2);fa[fx1]+=fa[fy2];fa[fy2]=fx1;}}int fy1=findfa(y),fx2=findfa(x+ot);if(fx2!=fy1){if(fa[fx2]>fa[fy1]){tr[now].u.push_back(fx2);fa[fy1]+=fa[fx2];fa[fx2]=fy1;}else{tr[now].u.push_back(fy1);fa[fx2]+=fa[fy1];fa[fy1]=fx2;}}if(findfa(fx1)==findfa(fx2)||findfa(fy1)==findfa(fy2))bk=false; } struct Answer{int l,r;bool b;}as[110000];int tp; void dfs(int now) {bool bk=true;for(int i=0;i<tr[now].id.size();i++)merge(now,bk,e[tr[now].id[i]].x,e[tr[now].id[i]].y);if(bk==false){as[++tp].l=tr[now].l,as[tp].r=tr[now].r,as[tp].b=false; }else{if(tr[now].l==tr[now].r)as[++tp].l=as[tp].r=tr[now].l,as[tp].b=true;else{dfs(tr[now].lc);dfs(tr[now].rc);}}for(int i=0;i<tr[now].u.size();i++)fa[tr[now].u[i]]=-1; }int main() {freopen("a.in","r",stdin);freopen("a.out","w",stdout);int n,m,T,st,ed;scanf("%d%d%d",&n,&m,&T);trlen=0;bt(1,T);for(int i=1;i<=m;i++){scanf("%d%d%d%d",&e[i].x,&e[i].y,&st,&ed);if(st>=ed){i--,m--;continue;}insert(1,st+1,ed,i);}memset(fa,-1,sizeof(fa));tp=0;dfs(1);for(int i=1;i<=tp;i++)for(int j=as[i].l;j<=as[i].r;j++)if(as[i].b)printf("Yes\n");else printf("No\n");return 0; }
转载于:https://www.cnblogs.com/AKCqhzdy/p/8516221.html
bzoj4025: 二分图相关推荐
- 【知识点总结】【CSP考前复习】图论大杂烩【未完】
序言 临近NOIP CSP-J 2019,不由得有些惆怅. 惆怅不是为了别的,主要是觉得从接触信息学竞赛开始,这已经是四个年头了,却一直拿的是二等奖.而今年是我最后的机会.如果不能成功,那自然就是AF ...
- 每周记录(4月底停更了qvq)
1月6日 旋转卡壳 闵可夫斯基和 1月13日 期末复习 1月20日 网络流前4道题 一场失败的期末考试 写寒假作业 bzoj [HNOI2008]明明的烦恼(90分) prufer序列 正睿 画画图 ...
- 【BZOJ4025】二分图(可撤销并查集+线段树分治)
题目: BZOJ4025 分析: 定理:一个图是二分图的充要条件是不存在奇环. 先考虑一个弱化的问题:保证所有边出现的时间段不会交叉,只会包含或相离. 还是不会?再考虑一个更弱化的问题:边只会出现不会 ...
- 【bzoj4025】二分图 LCT
题目描述 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考考你. 输入 输入数据的第一行是三 ...
- [BZOJ 4025] 二分图
题目传送-BZOJ4025 题意: 有一张\(n\)个节点的无向图,其中边\(i\)在\(s_i\)出现,\(e_i\)结束,并连接着节点\(x,y\). 并保证\(s_i < e_i \le ...
- POJ - 3041 Asteroids 二分图最小点覆盖
题目链接 二分图一个很重要的定理:看了很多大神的博客表示看不懂为什么,以后再看 最小点覆盖=最大匹配 最小点覆盖就是在二分图里边,选择一个点,将所有与该点相链接的边删去,问最小找多少个点能够把所有的边 ...
- P2172 [国家集训队]部落战争 二分图最小不相交路径覆盖
二分图最小不相交路径覆盖 #include<bits/stdc++.h> using namespace std; const int MAXN = 5550; const int MAX ...
- 图论:关于二分图的总结(转载)
二分图是这样一个图,它的顶点可以分类两个集合X和Y,所有的边关联在两个顶点中,恰好一个属于集合X,另一个属于集合Y. 最大匹配:图中包含边数最多的匹配称为图的最大匹配. 完美匹配:如果所有点都在匹配边 ...
- c语言最小费用流_策略算法工程师之路-图优化算法(一)(二分图amp;最小费用最大流)...
目录 1.图的基本定义 2.双边匹配问题 2.1 二分图基本概念 2.2 二分图最大匹配求解 2.3 二分图最优匹配求解 2.4 二分图最优匹配建模实例 2.4.1 二分图最优匹配在师生匹配中的应用 ...
最新文章
- python mainloop函数_python中的mainloop()函数
- php--------返回404状态
- 扫描过程_PLC的循环扫描工作过程
- 孙叫兽进阶之路之源代码配置管理过程(图文教程)
- Python string生成随机数
- 2.3.12 Python 函数进阶-装饰器
- PHP数据表记录自己信息,PHP对数据表记录的操作
- sqlserver监控(备忘)
- 乱七八糟 Nodejs 系列一:试水
- Servlet(四):转发与重定向、路径问题
- Oracle账户被锁定后如何解锁
- 免费的局域网协作办公方式—onlyoffice文档协作
- Python 爬取手机 豆果美食app存Mongodb
- ucenter 用户加密方式
- python:对英文段落进行分句(对一段英语进行整句切分,切分句子)
- 信号完整性(SI)电源完整性(PI)学习笔记(十四)有损线、上升边退化与材料特性(一)
- ESD:“蓝灯“精灵如何对抗27KV空气式放电
- Windows 安全资料库网站
- Python文字转换语音,让你的文字会「说话」,抠脚大汉秒变撒娇萌妹
- 基于T5CPU的智能屏产品型号与内核对照表
热门文章
- BZOJ 4720 [Noip2016]换教室
- WLAN高密无线网络部署的信道问题
- 阿里巴巴产品实习生N天
- 使用jQuery的hover事件在IE中不停闪动的解决方法
- IE中的CSS3不完全兼容方案
- Daily Scrum 2012/12/09
- C#递归的应用实例详解
- u-boot移植第二弹——移植2012.10u-boot到RealARM210 cortex-A8开发板
- windows 客户端的Navicat PL/SQL 连接Oracle 数据库
- java计算时间差_JAVA并发编程三大Bug源头(可见性、原子性、有序性),彻底弄懂...