ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【线段树优化建图】【P5029 T'ill It's Over】

2022-05-08 16:02:17  阅读:163  来源: 互联网

标签:连边 ch int 线段 节点 P5029 建图 编号 ill


【线段树优化建图】【P5029 T'ill It's Over】

P5029 T'ill It's Over

Analysis

每次将一个区间一块进行连边,可以用线段树优化,减少连边数。
具体在线段树每个节点维护一个编号,这个编号用一个tot来分配,在build时,每新建一个节点,tot++。将每个节点与它的左右儿子连边。
需要注意的是,既有将整个区间连向某个点的操作,也有将某个点连向整个区间的操作,因此线段树每个节点,实际需要维护两个编号,分别用来从下向上和从上向下连边。为了方便令这两个编号连续,所以只用维护一个编号。
区间加边时,就将区间在线段树上划分,再根据向上/向下连边即可。

Code

#include<bits/stdc++.h>
using namespace std;
//#define int long long
inline int read()
{
	register int x=0,w=1;
	register char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if(ch=='-') {w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*w;
}
inline void write(int x)
{
	if(x<0) putchar('-'),x=~(x-1);
	if(x>9) write(x/10);
	putchar('0'+x%10);
}
const int N=1e6+100,M=9*N,inf=1e7;
int n,m,k,hd[M],cnt=1,now[M],id[N<<2],s,t,tot,d[M];
struct node{
	int nxt,to,w;
}e[M<<1];
void add(int x,int y,int z)
{
	e[++cnt].nxt=hd[x],e[cnt].to=y,e[cnt].w=z,hd[x]=cnt;
	e[++cnt].nxt=hd[y],e[cnt].to=x,e[cnt].w=0,hd[y]=cnt;
}
void build(int x,int l,int r)
{
	id[x]=++tot;tot++;
	if(l==r){
		add(l,id[x],inf);add(id[x]+1,l,inf);return;
	}
	int mid=l+r>>1;
	build(x<<1,l,mid);build(x<<1|1,mid+1,r);
	add(id[x<<1],id[x],inf);add(id[x]+1,id[x<<1]+1,inf);
	add(id[x]+1,id[x<<1|1]+1,inf);add(id[x<<1|1],id[x],inf);
}
void change(int x,int L,int R,int l,int r,int op)
{
	if(L>=l&&R<=r){
		if(op) add(tot,id[x]+1,inf);
		else add(id[x],tot,inf);
		return;
	}
	int mid=L+R>>1;
	if(l<=mid) change(x<<1,L,mid,l,r,op);
	if(r>mid) change(x<<1|1,mid+1,R,l,r,op);
}
queue<int>q;
bool bfs()
{
	while(q.size()) q.pop();
	for(int i=1;i<=tot;++i) d[i]=0,now[i]=hd[i];
	d[s]=1;q.push(s);
	while(q.size())
	{
		int x=q.front();q.pop();
		for(int i=hd[x];i;i=e[i].nxt)
		{
			int y=e[i].to;if(d[y]||e[i].w==0) continue;
			d[y]=d[x]+1;q.push(y);
			if(y==t) return 1;
		}
	}
	return 0;
}
int dinic(int x,int flow)
{
	if(x==t) return flow;
	int rest=flow;
	for(int i=now[x];i&&rest;i=e[i].nxt)
	{
		now[x]=i;int y=e[i].to;
		if(d[y]==d[x]+1){
			int k=dinic(y,min(rest,e[i].w));
			if(k<min(rest,e[i].w)) d[y]=0;
			rest-=k;e[i].w-=k;e[i^1].w+=k;
		}
	}
	return flow-rest;
}
signed main()
{
    n=read();m=read();k=read();
    s=k+1,t=s+1,tot=t+1;
    build(1,1,k);
    for(int i=1;i<=m;++i){
    	int op=read(),l=read(),x,y,u,v;
    	if(op==1){
    		x=y=read(),u=v=read();
		}
		else if(op==2) x=read(),y=read(),u=v=read();
		else if(op==3) x=y=read(),u=read(),v=read();
		else x=read(),y=read(),u=read(),v=read();
		tot++;change(1,1,k,x,y,0);add(tot,tot+1,l);tot++;change(1,1,k,u,v,1);
	}
	add(s,1,n);add(k,t,n);int ans=0;
	while(bfs()) ans+=dinic(s,inf);
	write(ans);
	return 0;
}

标签:连边,ch,int,线段,节点,P5029,建图,编号,ill
来源: https://www.cnblogs.com/glq-Blog/p/16245802.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有