loj536「LibreOJ Round #6」花札(二分圖博弈)
阿新 • • 發佈:2020-07-15
loj536「LibreOJ Round #6」花札(二分圖博弈)
題解時間
很明顯是二分圖博弈。
以某個點為起點,先手必勝的充要條件是起點一定在最大匹配中。
判斷方法是看起點到該點的邊有流量且該點不在起點割集中。
#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();}