• 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
    ",ans[i]);
    	return 0;
    }
    }
    int main(){return RKK::main();}
    
  • 相关阅读:
    计算2*3+(2*(5+6)*3)/2+4*6的值
    单链表 删除倒数第m个元素的实现
    string.data()和string.c_str()
    c++ 打印时间
    二分查找
    两个整数相除的计算
    查看一个数字是不是回环数(对称)
    编译#include <stdio.h> 等用尖括号指定的文件提示找不到 VS googleTest 安装的makeInstall
    八皇后---递归
    分治算法--求m的n次方
  • 原文地址:https://www.cnblogs.com/rikurika/p/13307195.html
Copyright © 2020-2023  润新知