[BZOJ1305][CQOI2009]dance跳舞(枚举二分+最大流)
2016-05-02 17:35
447 查看
题目描述
传送门题解
刚开始写的是二分,但是没调对,索性改了枚举,不过跑得也挺快的。首先拆点xiyi,没什么具体含义,喔可能一个是在互相喜欢的那一堆里连的,另一个是在互相不喜欢的那一堆里连的。
枚举能进行几场舞会,假设枚举到的是mid
对于所有的boy,s->xi mid,对于所有的girl,xi->t mid
对于互相喜欢的i和j,xi->xj 1,对于互相不喜欢的i和j,yi->yj 1
对于所有的boy xi->yi k 对于所有的girl yi->xi k
跑一边最大流,如果maxflow
代码
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int max_n=5000; const int max_m=1e5+5; const int max_e=max_m*2; const int INF=1e9; char s[100]; int n,k,N,mid,maxflow,ans; int tot,point[max_n],next[max_e],v[max_e],remain[max_e]; int like[100][100],deep[max_n],num[max_n],last[max_n],cur[max_n]; queue<int>q; inline void addedge(int x,int y,int cap){ ++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap; ++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0; } inline void bfs(int t){ for (int i=1;i<=N;++i) deep[i]=N; deep[t]=0; while (!q.empty()) q.pop(); q.push(t); while (!q.empty()){ int now=q.front(); q.pop(); for (int i=point[now];i!=-1;i=next[i]) if (deep[v[i]]==N&&remain[i^1]){ deep[v[i]]=deep[now]+1; q.push(v[i]); } } } inline int addflow(int s,int t){ int now=t,ans=INF; while (now!=s){ ans=min(ans,remain[last[now]]); now=v[last[now]^1]; } now=t; while (now!=s){ remain[last[now]]-=ans; remain[last[now]^1]+=ans; now=v[last[now]^1]; } return ans; } inline void isap(int s,int t){ bfs(t); for (int i=1;i<=N;++i) ++num[deep[i]]; for (int i=1;i<=N;++i) cur[i]=point[i]; int now=s; while (deep[s]<N){ if (now==t){ maxflow+=addflow(s,t); now=s; } bool has_find=false; for (int i=cur[now];i!=-1;i=next[i]) if (deep[v[i]]+1==deep[now]&&remain[i]){ has_find=true; cur[now]=i; last[v[i]]=i; now=v[i]; break; } if (!has_find){ int minn=N-1; for (int i=point[now];i!=-1;i=next[i]) if (remain[i]) minn=min(minn,deep[v[i]]); if (!(--num[deep[now]])) break; ++num[deep[now]=minn+1]; cur[now]=point[now]; if (now!=s) now=v[last[now]^1]; } } } int main(){ scanf("%d%d\n",&n,&k); for (int i=1;i<=n;++i){ gets(s); for (int j=1;j<=n;++j) if (s[j-1]=='Y') like[i][j]=1; else like[i][j]=0; } N=4*n+2; for (mid=1;;++mid){ tot=-1; memset(point,-1,sizeof(point)); memset(next,-1,sizeof(next)); for (int i=1;i<=n;++i) addedge(1,1+i,mid); for (int i=1;i<=n;++i) addedge(1+i+n,N,mid); for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) if (like[i][j]) addedge(1+i,1+n+j,1); for (int i=1;i<=n;++i) addedge(1+i,1+2*n+i,k),addedge(1+3*n+i,1+n+i,k); for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) if (!like[i][j]) addedge(1+2*n+i,1+3*n+j,1); maxflow=0,isap(1,N); if (maxflow<n*mid) break; } printf("%d\n",mid-1); } ?
总结
网络流能不能再考场上写对?写错了能不能调?相关文章推荐
- hdu 5311 Hidden String(dfs)
- 学习android第四周总结相对布局和线性布局常用属性的作用
- hduoj Train Problem I-1022
- scala学习(1)——hello world
- Rolle定理的证明_20160402
- [BZOJ3524][Poi2014]Couriers(主席树)
- STM32时钟源
- 怎样用产品思维来做好PPT
- android studio 工具
- hdu 5339 Untitled (dfs)
- 图片做按钮
- IO端口和IO内存的区别 转
- 福州大学第十三届程序设计竞赛_重现解题报告
- visual studio 版本号(vc、vs)
- LU分解(matlab实现)
- HDU-4856 Tunnels(BFS&&状压DP)
- 2013山东省第三届ACM省赛 Mine Number
- linux tar .gz .zip 打包 解压缩 压缩命令
- 02-线性结构1 一元多项式的乘法与加法运算[网易云课堂-数据结构]
- Android图片压缩终极解决方案,是的,终极,终极,终极