loj536「LibreOJ Round #6」花札(二分图博弈)

loj536「LibreOJ Round #6」花札(二分图博弈)

loj

题解时间

很明显是二分图博弈。

以某个点为起点,先手必胜的充要条件是起点一定在最大匹配中

判断方法是看起点到该点的边有流量且该点不在起点割集中。

#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
struct pat{int x,y;pat(int x=0,int y=0):x(x),y(y){}bool operator<(const pat &p)const{return x==p.x?y<p.y:x<p.x;}};
template<typename TP>inline void read(TP &tar)
{
	TP ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){ret=ret*10+(ch-'0');ch=getchar();}
	tar=ret*f;
}
template<typename TP,typename... Args>inline void read(TP& t,Args&... args){read(t),read(args...);}
namespace RKK
{
const int D=40011,N=100011,M=300011,inf=0x3f3f3f3f;
struct sumireko{int to,ne;int w;}e[M<<1];int he[N],ecnt=1;
void addline(int f,int t,int w)
{
	e[++ecnt].to=t,e[ecnt].w=w;e[ecnt].ne=he[f],he[f]=ecnt;
	e[++ecnt].to=f,e[ecnt].w=0;e[ecnt].ne=he[t],he[t]=ecnt;
}
void dddline(int f,int t,int w)
{
	e[++ecnt].to=t,e[ecnt].w=w;e[ecnt].ne=he[f],he[f]=ecnt;
	e[++ecnt].to=f,e[ecnt].w=w;e[ecnt].ne=he[t],he[t]=ecnt;
}

int sp,ep;
int dep[N],cur[N];
queue<int> q;
int bfs(int sp,int ep)
{
	memset(dep,0x00,sizeof(dep));
	memcpy(cur,he,sizeof(cur));
	q.push(sp),dep[sp]=1;
	while(!q.empty())
	{
		int x=q.front();q.pop();
		for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)if(e[i].w&&!dep[t])
			q.push(t),dep[t]=dep[x]+1;
	}
	return dep[ep]!=0;
}
int dfs(int x,int ep,int lim)
{
	if(!lim||x==ep) return lim;
	int ret=0,tmp;
	for(int &i=cur[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)
	if(dep[t]==dep[x]+1&&(tmp=dfs(t,ep,min(e[i].w,lim))))
	{
		ret+=tmp,lim-=tmp;
		e[i].w-=tmp,e[i^1].w+=tmp;
		if(!lim) break;
	}
	return ret;
}
int dinic(int sp,int ep){int ret=0;while(bfs(sp,ep)) ret+=dfs(sp,ep,inf);return ret;}

int m1,m2,n1,n2;
int x1[D],y1[D],x2[D],y2[D];
int ans[D];

int main()
{
	read(m1,m2);
	read(n1);for(int i=1;i<=n1;i++) read(x1[i],y1[i]);
	read(n2);for(int i=1;i<=n2;i++) read(x2[i],y2[i]);
	sp=n1+n2+m1+m2+1,ep=sp+1;
	for(int i=1;i<=n1;i++) addline(sp,i,1),addline(i,n1+n2+x1[i],1),addline(i,n1+n2+m1+y1[i],1);
	for(int i=1;i<=n2;i++) addline(n1+i,ep,1),addline(n1+n2+x2[i],n1+i,1),addline(n1+n2+m1+y2[i],n1+i,1);
	dinic(sp,ep);for(int i=he[sp],t=e[i].to;i;i=e[i].ne,t=e[i].to)
		if(!e[i].w&&!dep[t]) ans[t]=1;
	for(int i=1;i<=n1;i++) printf("%d\n",ans[i]);
	return 0;
}
}
int main(){return RKK::main();}
posted @ 2020-07-15 18:29  RikukiIX  阅读(296)  评论(0编辑  收藏  举报