「学习笔记」网络战争 - KD-Tree - 最小割树 - 学习笔记

题目大意就是让你实现一个KDT和最小割树(大雾)
然后发现两个都不会,就赶紧去学习了一发姿势。
顺带练习了一发namespace都的使用姿势。
KDT本质上就是个做剪枝的过程,很好理解。
最小割树是这样的,每次随便选择一个S和T,然后求出最小割w,然后在最小割树上连(S,T,w)即可。然后一对点的最小割是路径上都的最小值。
(这垃圾题写了将进7个k也真爽翻了的说

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<vector>
#include<queue>
#include<assert.h>
#define mp make_pair
#define fir first
#define sec second
#define pb push_back
#define gc getchar()
#define INF (INT_MAX/2-10)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef pair<pii,int> piii;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int squ(int x) { return x*x; }
inline int gabs(int x) { return x<0?-x:x; }
const int N=50010;
int des[N],nc[N];vector<piii> es[N];
struct P{
	static int cur_dim;int x[2],id,to;
	P(int _x=0,int _y=0,int _id=0,int _to=0) { x[0]=_x,x[1]=_y,id=_id,to=_to; }
	inline P operator=(const P &p) { return x[0]=p.x[0],x[1]=p.x[1],id=p.id,to=p.to,*this; }
	inline int dis2(const P &p)const { return squ(x[0]-p.x[0])+squ(x[1]-p.x[1]); }
	inline bool operator==(const P &p)const { return id==p.id; }
	inline bool operator!=(const P &p)const { return id!=p.id; }
	inline bool operator<(const P &p)const { return x[cur_dim]<p.x[cur_dim]; }
	inline int input(int _i) { return scanf("%d%d",x,x+1),id=_i; }
	inline int show()const { return cerr<<"("<<x[0]<<", "<<x[1]<<")"<<endl,0; }
}p[50010];
int P::cur_dim=0;
namespace KDT_space{
	struct KDT_node{KDT_node *ch[2];P p;bool islf;int dim,pos;};
	P nst;int bstd;
	struct KDT{
		KDT_node *rt;
		inline int build(P *p,int n) { return build(rt,p,1,n,0); }
		int build(KDT_node* &rt,P *p,int l,int r,int dim)
		{
			P::cur_dim=dim,rt=new KDT_node,rt->dim=dim,rt->islf=0;
			if(l==r) return rt->p=p[l],rt->islf=1;int mid=(l+r)>>1;
			nth_element(p+l,p+mid,p+r+1),rt->pos=p[mid].x[dim];
			return build(rt->ch[0],p,l,mid,dim^1),build(rt->ch[1],p,mid+1,r,dim^1),0;
		}
		inline P find(const P &p) { return bstd=INF,find(rt,p),nst; }
		int find(KDT_node* &rt,const P &p)
		{
			if(rt->islf)
			{
				int d;if(p==rt->p||(d=p.dis2(rt->p))>bstd) return 0;
				if(d<bstd||nst.id>=rt->p.id) bstd=d,nst=rt->p;return 0;
			}
			int dim=rt->dim,pos=rt->pos,g=(p.x[dim]>pos);find(rt->ch[g],p);
			if(squ(gabs(p.x[dim]-pos))<=bstd) find(rt->ch[g^1],p);return 0;
		}
	}kdt;
}
using KDT_space::kdt;
namespace BIGTREE_space{
	const int N=50010,LOG=18;
	vector<pii> to[N],g[N];int bel[N];
	int d[N],up[N][LOG],mnv[N][LOG],Log[N];
	struct BIGTREE{
		int dfs(int x,int fa,int bl)
		{
			up[x][0]=fa,d[x]=d[fa]+1;
			for(int i=1;i<=Log[d[x]];i++)
				up[x][i]=up[up[x][i-1]][i-1],
				mnv[x][i]=min(mnv[x][i-1],mnv[up[x][i-1]][i-1]);
			for(int i=0,y;i<(int)g[x].size();i++)
				if((y=g[x][i].fir)^fa) mnv[y][0]=g[x][i].sec,dfs(y,x,bl);
			return bel[x]=bl;
		}
		inline int query(int x,int y)
		{
			if(bel[x]!=bel[y]) return 0;
			if(d[x]<d[y]) swap(x,y);int ans=INF;
			for(int i=Log[d[x]];i>=0;i--)
				if(d[up[x][i]]>=d[y]) ans=min(ans,mnv[x][i]),x=up[x][i];
			if(x==y) return ans;
			for(int i=Log[d[x]];i>=0;i--) if(up[x][i]^up[y][i])
				ans=min(ans,min(mnv[x][i],mnv[y][i])),x=up[x][i],y=up[y][i];
			return min(ans,min(mnv[x][0],mnv[y][0]));
		}
		inline int build(P *p,int n)
		{
			for(int i=1,x,y;i<=n;i++)
				x=p[i].id,y=p[i].to,to[x].pb(mp(y,des[x])),to[y].pb(mp(x,des[x]));
			rep(x,1,n)
			{
				sort(to[x].begin(),to[x].end());
				for(int i=0,j;i<(int)to[x].size();g[x].pb(mp(to[x][i].fir,to[x][i].sec)),i=j)
					for(j=i+1;j<(int)to[x].size()&&to[x][i].fir==to[x][j].fir;to[x][i].sec+=to[x][j++].sec);
			}
			for(int i=2;i<=n;i++) Log[i]=Log[i>>1]+1;
			for(int i=1;i<=n;i++) if(!bel[i]) dfs(i,0,i);
			return 0;
		}
	}bigtree;
}
using BIGTREE_space::bigtree;
namespace MCT_space{
	const int N=2010,M=4010,LOG=14;
	queue<int> q;
	struct edges{
		int to,pre,resf,fsav;
	}e[M];int h[N],cur[N],etop,lev[N],p[N],a[N];
	inline int add_edge(int u,int v,int f)
	{	int x=++etop;e[x].to=v,e[x].pre=h[u],h[u]=x;return e[x].resf=e[x].fsav=f,etop;	}
	inline int build_edge(int u,int v,int f) { return add_edge(u,v,f),add_edge(v,u,f);	}
	inline int bfs(int s,int t,int n)
	{
		memset(lev,0,sizeof(int)*(n+1));
		while(!q.empty()) q.pop();
		q.push(s),lev[s]=1;
		while(!q.empty())
		{
			int x=q.front();q.pop();
			for(int i=h[x],y;i;i=e[i].pre)
				if(!lev[y=e[i].to]&&e[i].resf)
					q.push(y),lev[y]=lev[x]+1;
		}
		return lev[t]>0;
	}
	int dfs(int s,int t,int a)
	{
		if(s==t||!a) return a;int flow=0,f;
		for(int &i=cur[s];i;i=e[i].pre)
			if(lev[e[i].to]==lev[s]+1&&(f=dfs(e[i].to,t,min(a,e[i].resf)))>0)
			{	e[i].resf-=f,e[((i-1)^1)+1].resf+=f,a-=f,flow+=f;if(!a) break;	}
		return flow;
	}
	inline int dinic(int s,int t,int n)
	{	int flow=0;while(bfs(s,t,n)) memcpy(cur,h,sizeof(int)*(n+1)),flow+=dfs(s,t,INF);return flow;	}
	struct MCT{
		int n;vector<int> Log,d;
		vector<vector<int> > up,mnv;
		vector<vector<pii> > g;
		int getup(int x,int fa=0,int v=0)
		{
			up[x].resize(LOG+1),up[x][0]=fa,d[x]=d[fa]+1;
			mnv[x].resize(LOG+1),mnv[x][0]=v;
			for(int i=1;i<=Log[d[x]];i++)
				up[x][i]=up[up[x][i-1]][i-1],
				mnv[x][i]=min(mnv[x][i-1],mnv[up[x][i-1]][i-1]);
			for(int i=0,y;i<(int)g[x].size();i++)
				if((y=g[x][i].fir)^fa) getup(y,x,g[x][i].sec);
			return 0;
		}
		inline int query(int x,int y)
		{
			if(d[x]<d[y]) swap(x,y);int ans=INF;
			for(int i=Log[d[x]];i>=0;i--)
				if(d[up[x][i]]>=d[y]) ans=min(ans,mnv[x][i]),x=up[x][i];
			if(x==y) return ans;
			for(int i=Log[d[x]];i>=0;i--)
				if(up[x][i]^up[y][i]) ans=min(ans,min(mnv[x][i],mnv[y][i])),x=up[x][i],y=up[y][i];
			return min(ans,min(mnv[x][0],mnv[y][0]));
		}
		inline int build(vector<piii> &es,int _nc)
		{
			n=_nc;memset(h,0,sizeof(int)*(n+1)),etop=0;
			Rep(i,es) build_edge(es[i].fir.fir,es[i].fir.sec,es[i].sec);
			g.resize(n+1),Log.resize(n+1),up.resize(n+1),mnv.resize(n+1);
			rep(i,2,n) Log[i]=Log[i>>1]+1;d.resize(n+1);
			rep(i,1,n) p[i]=i;build(1,n);getup(1);return 0;
		}
		int build(int l,int r)
		{
			if(l==r) return 0;int s=p[l],t=p[r];
			rep(x,1,n) for(int i=h[x];i;i=e[i].pre) e[i].resf=e[i].fsav;
			int w=dinic(s,t,n),L=l-1,R=r+1;g[s].pb(mp(t,w)),g[t].pb(mp(s,w));
			rep(i,l,r) if(lev[p[i]]) a[++L]=p[i];else a[--R]=p[i];
			memcpy(p+l,a+l,sizeof(int)*(r-l+1));return build(l,L),build(R,r);
		}
	}mct[50010];
}
using MCT_space::mct;
int main()
{
	int n=inn(),u,v,m;
	rep(i,1,n)
	{
		p[i].input(i),des[i]=inn(),nc[i]=inn(),m=inn();
		while(m--) u=inn(),v=inn(),es[i].pb(mp(mp(u,v),inn()));
	}
	kdt.build(p,n);rep(i,1,n) p[i].to=kdt.find(p[i]).id;
	bigtree.build(p,n);rep(i,1,n) mct[i].build(es[i],nc[i]);
	for(int q=inn();q;q--)
	{
		int x=inn(),y=inn(),a=inn(),b=inn();
		if(x==y) { printf("%d\n",mct[x].query(a,b));continue; }
		int ans=bigtree.query(x,y);
		ans=min(ans,mct[x].query(1,a));
		ans=min(ans,mct[y].query(1,b));
		printf("%d\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82814054