这题想不出来。

不浪费时间了。

以后找时间填。

--------------------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: 二分图相关推荐

  1. 【知识点总结】【CSP考前复习】图论大杂烩【未完】

    序言 临近NOIP CSP-J 2019,不由得有些惆怅. 惆怅不是为了别的,主要是觉得从接触信息学竞赛开始,这已经是四个年头了,却一直拿的是二等奖.而今年是我最后的机会.如果不能成功,那自然就是AF ...

  2. 每周记录(4月底停更了qvq)

    1月6日 旋转卡壳 闵可夫斯基和 1月13日 期末复习 1月20日 网络流前4道题 一场失败的期末考试 写寒假作业 bzoj [HNOI2008]明明的烦恼(90分) prufer序列 正睿 画画图 ...

  3. 【BZOJ4025】二分图(可撤销并查集+线段树分治)

    题目: BZOJ4025 分析: 定理:一个图是二分图的充要条件是不存在奇环. 先考虑一个弱化的问题:保证所有边出现的时间段不会交叉,只会包含或相离. 还是不会?再考虑一个更弱化的问题:边只会出现不会 ...

  4. 【bzoj4025】二分图 LCT

    题目描述 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于是他想考考你. 输入 输入数据的第一行是三 ...

  5. [BZOJ 4025] 二分图

    题目传送-BZOJ4025 题意: 有一张\(n\)个节点的无向图,其中边\(i\)在\(s_i\)出现,\(e_i\)结束,并连接着节点\(x,y\). 并保证\(s_i < e_i \le ...

  6. POJ - 3041 Asteroids 二分图最小点覆盖

    题目链接 二分图一个很重要的定理:看了很多大神的博客表示看不懂为什么,以后再看 最小点覆盖=最大匹配 最小点覆盖就是在二分图里边,选择一个点,将所有与该点相链接的边删去,问最小找多少个点能够把所有的边 ...

  7. P2172 [国家集训队]部落战争 二分图最小不相交路径覆盖

    二分图最小不相交路径覆盖 #include<bits/stdc++.h> using namespace std; const int MAXN = 5550; const int MAX ...

  8. 图论:关于二分图的总结(转载)

    二分图是这样一个图,它的顶点可以分类两个集合X和Y,所有的边关联在两个顶点中,恰好一个属于集合X,另一个属于集合Y. 最大匹配:图中包含边数最多的匹配称为图的最大匹配. 完美匹配:如果所有点都在匹配边 ...

  9. c语言最小费用流_策略算法工程师之路-图优化算法(一)(二分图amp;最小费用最大流)...

    目录 1.图的基本定义 2.双边匹配问题 2.1 二分图基本概念 2.2 二分图最大匹配求解 2.3 二分图最优匹配求解 2.4 二分图最优匹配建模实例 2.4.1 二分图最优匹配在师生匹配中的应用 ...

最新文章

  1. python mainloop函数_python中的mainloop()函数
  2. php--------返回404状态
  3. 扫描过程_PLC的循环扫描工作过程
  4. 孙叫兽进阶之路之源代码配置管理过程(图文教程)
  5. Python string生成随机数
  6. 2.3.12 Python 函数进阶-装饰器
  7. PHP数据表记录自己信息,PHP对数据表记录的操作
  8. sqlserver监控(备忘)
  9. 乱七八糟 Nodejs 系列一:试水
  10. Servlet(四):转发与重定向、路径问题
  11. Oracle账户被锁定后如何解锁
  12. 免费的局域网协作办公方式—onlyoffice文档协作
  13. Python 爬取手机 豆果美食app存Mongodb
  14. ucenter 用户加密方式
  15. python:对英文段落进行分句(对一段英语进行整句切分,切分句子)
  16. 信号完整性(SI)电源完整性(PI)学习笔记(十四)有损线、上升边退化与材料特性(一)
  17. ESD:“蓝灯“精灵如何对抗27KV空气式放电
  18. Windows 安全资料库网站
  19. Python文字转换语音,让你的文字会「说话」,抠脚大汉秒变撒娇萌妹
  20. 基于T5CPU的智能屏产品型号与内核对照表

热门文章

  1. BZOJ 4720 [Noip2016]换教室
  2. WLAN高密无线网络部署的信道问题
  3. 阿里巴巴产品实习生N天
  4. 使用jQuery的hover事件在IE中不停闪动的解决方法
  5. IE中的CSS3不完全兼容方案
  6. Daily Scrum 2012/12/09
  7. C#递归的应用实例详解
  8. u-boot移植第二弹——移植2012.10u-boot到RealARM210 cortex-A8开发板
  9. windows 客户端的Navicat PL/SQL 连接Oracle 数据库
  10. java计算时间差_JAVA并发编程三大Bug源头(可见性、原子性、有序性),彻底弄懂...