[二分图最大匹配必配点] BZOJ 3546 [ONTAK2010]Life of the Party
2016-08-05 14:50
302 查看
%%%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 ,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 ; int Q ,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 ; 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 ,y ; int left ,right ; 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 ,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 ,girl ; #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; }
相关文章推荐
- 09、CSS3新增背景属性
- 关于JS原型链
- AngularJS学习之angular.extend用法实例
- Angular外部使用js调用Angular控制器中的函数方法或变量用法示例
- ajax同步开发——json+对应的处理方式直接贴上被我滥用的代码标本吧:
- D3.js学习总结
- 用面向对象的编程思想去写js
- JQuery插件编写
- 剑指offer56--二叉树的序列化和反序列化
- bootstrap模态框点击空白处模态框不消失、监听模态框打开还是关闭
- 一些有用的HTML5 pattern属性
- 关于css中列表(ul ol)存在默认间距的问题
- 前后台json数据绑定——way.JS
- 前端学习Sublime篇(四)
- [leetcode]304. Range Sum Query 2D - Immutable -- JavaScript 代码
- jquery 获取所有选中的多选按钮的值,附:获取未选中的所有多选按钮的值
- Butterknife 绑定控件后,点击事件判断为空,问题解决方法一
- 轻松理解javascript中的闭包
- jQuery对表单的操作
- JavaScript事件概览