[二分图最大匹配必配点] BZOJ 3546 [ONTAK2010]Life of the Party
来源:互联网 发布:mac 照片 相簿 文件夹 编辑:程序博客网 时间:2024/05/23 11:03
%%%dyh
首先求出最大匹配,下面考虑左边点的情况。
我们将匹配中的边从右往左连,不在匹配中的边从左往右连。
这个时候一条增广路成为一条连续的路径。
从每个左边未匹配的点还是遍历,如果被一个左边的点被访问到,说明存在一条增广路,也就是不一定在最大匹配中。
所有没有被访问到的点一定在最大匹配中。
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #define cl(x) memset(x,0,sizeof(x)) #define V G[p].v using namespace std; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } namespace DINIC{ const int N=20005; const int M=300005; struct edge{ int u,v,f; int next; }G[M]; int head[N],inum=1; inline void add(int u,int v,int f,int p){ G[p].u=u; G[p].v=v; G[p].f=f; G[p].next=head[u]; head[u]=p; } inline void link(int u,int v,int f){ add(u,v,f,++inum); add(v,u,0,++inum); } int S,T; int dis[N]; int Q[N],l,r; inline bool bfs(){ memset(dis,-1,sizeof(dis)); l=r=-1; Q[++r]=S; dis[S]=1; while (l<r){ int u=Q[++l]; for (int p=head[u];p;p=G[p].next) if (G[p].f && dis[V]==-1){ dis[V]=dis[u]+1; Q[++r]=V; if (V==T) return 1; } } return 0; } int cur[N]; int dfs(int u,int flow){ if (u==T) return flow; int used=0,now; for (int p=cur[u];p;p=G[p].next) { cur[u]=p; if (G[p].f && dis[V]==dis[u]+1) { now=dfs(V,min(flow-used,(int)G[p].f)); G[p].f-=now,G[p^1].f+=now; used+=now; if (flow==used) break; } } if (!used) dis[u]=-1; return used; } int Dinic(){ int ret=0; while (bfs()) memcpy(cur,head,sizeof(cur)),ret+=dfs(S,1<<30); return ret; } } const int N=100005; int n,m,K; int x[N],y[N]; int left[N],right[N]; inline void Match() { using namespace DINIC; S=n+m+1,T=n+m+2; for (int i=1;i<=K;i++) link(x[i],n+y[i],1<<30); for (int i=1;i<=n;i++) link(S,i,1); for (int i=1;i<=m;i++) link(n+i,T,1); Dinic(); for (int i=1;i<=K;i++) { int p=2*i; if (G[p^1].f) left[y[i]]=x[i],right[x[i]]=y[i]; } } struct edge{ int u,v,next; }G[N<<3]; int head[N],inum; inline void add(int u,int v,int p){ G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p; } int vst[N<<2]; int boy[N],girl[N]; #define V G[p].v inline void dfs(int u) { if (vst[u]) return; vst[u]=1; for (int p=head[u];p;p=G[p].next) dfs(V); } int main() { read(n); read(m); read(K); for (int i=1;i<=K;i++) read(x[i]),read(y[i]); Match(); for (int i=1;i<=K;i++) if (left[y[i]]==x[i]) add(n+y[i],x[i],++inum); else add(x[i],n+y[i],++inum); for (int i=1;i<=n;i++) if (!right[i]) dfs(i); for (int i=1;i<=n;i++) if (!vst[i]) printf("%d\n",i); cl(vst); cl(head); inum=0; for (int i=1;i<=K;i++) if (left[y[i]]!=x[i]) add(n+y[i],x[i],++inum); else add(x[i],n+y[i],++inum); for (int i=1;i<=m;i++) if (!left[i]) dfs(n+i); for (int i=1;i<=m;i++) if (!vst[n+i]) printf("%d\n",i); return 0; }
0 0
- [二分图最大匹配必配点] BZOJ 3546 [ONTAK2010]Life of the Party
- bzoj3546: [ONTAK2010]Life of the Party
- hdu2444 The Accomodation of Students (二分图判断+最大匹配)
- hdu2444 The Accomodation of Students【二分图判断+最大匹配】
- [BZOJ]4950 二分图 + 最大匹配
- bzoj 4950(二分图最大匹配)
- [BZOJ]3140 二分图最大匹配
- BZOJ 1191(二分图最大匹配)
- hdu2444 The Accomodation of Students(判断二分匹配+最大匹配)
- HDU 2444 The Accomodation of Students 判断是否为二分图,二分图的最大匹配
- hdu 2444 The Accomodation of Students (判断二分图,二分图最大匹配)
- HDU 2444 The Accomodation of Students (二分图最大匹配+二分图染色)
- hdu 2444 The Accomodation of Students(判断二分图,二分图最大匹配)
- hdu 2444 The Accomodation of Students(二分图判断,二分图最大匹配)
- The Accomodation of Students(二分图的判断+二分图的最大匹配)
- hdu 2444 The Accomodation of Students(是否二分图,找二分最大匹配数)
- hdu 2444 The Accomodation of Students【二分图染色+最大二分匹配数】
- HDU 2444 The Accomodation of Students(二分图判断+最大二分匹配)
- RFC6020 - YANG语言标准中文
- 解决ie打开url返回json/map自动下载
- MFC关闭窗口 退出软件的 用法
- 关于JS原型链
- 在Myeclipse中给Maven项目添加框架支持
- [二分图最大匹配必配点] BZOJ 3546 [ONTAK2010]Life of the Party
- circle POJ动态规划某一题。。题号。。。额。。。。
- friend 关键字 对于模板 并不仅仅只是友元!!!
- 笔记1——C++多态与Java多态的异同
- 快速第三方入口(持续关注)
- AngularJS学习之Controller控制器之间的通信
- iOS程序逆向Mac下常用工具——Reveal、HopperDisassemble、IDA
- [LeetCode]--143. Reorder List(Python + Java)
- 嘟嘟聊Unity:写给不知如何学Unity3D的爱好者