hdu3081 最大流
来源:互联网 发布:当兵对网络教育学籍 编辑:程序博客网 时间:2024/06/16 23:44
思路见来自某大牛:
题目大意:n个男孩n个女孩,女孩选男孩,每个女孩都要选到不同的人k对女孩有相同选择标准,女孩每轮都选择没选过的男孩,问总共能选几轮。题解:女孩1..n,男孩n+1..2*n编号由女孩到男孩建容量为1的边起点st=2*n+1,到1..n建边;n+1..2*n到终点ed=2*n+2建边二分搜索最大容量即为答案;#include <iostream>#include <cstring>#include <cstdio>#define MAXN 210#define MAXM 50000using namespace std;struct node{ int u,v,w;};struct node2{ int x,y;};node2 ee[MAXM];int first[210],p[MAXN];node e[MAXM];int next[MAXM],cc,n,m,f;int gap[210],d[210],curedges[210],pre[210];int map[105][105];inline void add_edge(int u,int v,int w){ e[cc].u=u; e[cc].v=v; e[cc].w=w; next[cc]=first[u]; first[u]=cc; cc++; e[cc].u=v; e[cc].v=u; e[cc].w=0; next[cc]=first[v]; first[v]=cc; cc++;}void make_set(int n){ int i; for(i=0;i<=n;i++) p[i]=i;}int find_set(int i){ int j=i; while(j!=p[j]) j=p[j]; return p[i]=j;}int Union(int x,int y){ x=find_set(x); y=find_set(y); if(x==y) return 0; else { p[x]=y; return 1; }}void build(int t,int mid){ cc=0; int i,j; memset(map,0,sizeof(map)); memset(first,-1,sizeof(first)); memset(next,-1,sizeof(next)); for(i=1;i<=n;i++) { add_edge(0,i,mid); add_edge(n+i,t,mid); } for(i=0;i<m;i++) { int u=ee[i].x; int v=ee[i].y; for(j=1;j<=n;j++) { if(find_set(u)==find_set(j)) if(!map[j][v]) { map[j][v]=1; add_edge(j,n+v,1); } } }}int sap(int s,int t){ int cur_flow,flow_ans=0,u,tmp,neck,i; memset(d,0,sizeof(d)); memset(gap,0,sizeof(gap)); memset(pre,-1,sizeof(sizeof(pre))); for(i=0;i<=t;i++) curedges[i]=first[i]; gap[0]=t+1; u=s; while(d[s]<t+1) { if(u==t) { cur_flow=99999999; for(i=s;i!=t;i=e[curedges[i]].v) { if(cur_flow>e[curedges[i]].w) { neck=i; cur_flow=e[curedges[i]].w; } } for(i=s;i!=t;i=e[curedges[i]].v) { tmp=curedges[i]; e[tmp].w-=cur_flow; e[tmp^1].w+=cur_flow; } flow_ans+=cur_flow; u=neck; } for(i=curedges[u];i!=-1;i=next[i]) if(e[i].w&&d[u]==d[e[i].v]+1) break; if(i!=-1) { curedges[u]=i; pre[e[i].v]=u; u=e[i].v; } else { if(0==--gap[d[u]]) break; curedges[u]=first[u]; for(tmp=t+1,i=first[u];i!=-1;i=next[i]) if(e[i].w) tmp=min(tmp,d[e[i].v]); d[u]=tmp+1; ++gap[d[u]]; if(u!=s) u=pre[u]; } } return flow_ans;}int main(){ int T; scanf("%d",&T); while(T--) { memset(ee,0,sizeof(ee)); memset(e,0,sizeof(e)); scanf("%d%d%d",&n,&m,&f); int i,s=0,t=n*2+1; for(i=0;i<m;i++) scanf("%d%d",&ee[i].x,&ee[i].y); make_set(t); for(i=0;i<f;i++) { int u,v; scanf("%d%d",&u,&v); Union(u,v); } int l=0,r=n,ans=0; while(l<=r) { int mid=(l+r)>>1; build(t,mid); int res=sap(s,t); if(res>=mid*n) { ans=mid; l=mid+1; } else r=mid-1; } printf("%d\n",ans); } return 0;}
刚开始一直WA后来发现原来是要每运行一次SAP就要建一次图~~因为运行后会改变图的W~~~
- hdu3081 最大流
- hdu3081 Marriage Match II 二分+最大流
- HDU3081 Marriage Match II(最大流)
- hdu3081 二分+并查集+最大流
- 【hdu3081】【二分法】【最大流】【并查集】Marriage Match II
- HDU3081 使用Floyd传递关系,二分最大流
- hdu3081 Marriage Match II 最大流+二分+并查集
- hdu3081 二分 网络流
- HDU3081 3081 Marriage Match II(中等,好题)([二分最大流]+并查集)
- HDU3081 Marriage Match II 【最大匹配】
- HDU3081-并查集+最大二分匹配
- 【网络流】hdu3081 Marriage Match II
- 【网络流】【HDU3081】Marriage Match II
- HDU3081 Marriage Match II【网络流】
- hdu3081—Marriage Match II(并查集+最大匹配)
- hdu3081 双向广搜
- HDU3081二分匹配
- hdu3081 Marriage Match II
- ZOJ 3700 Ever Dream(字符串)
- 将VIM作为简易IDE
- ruby run case
- ZOJ 3702 Gibonacci number
- IBM X3850 M4装MS SERVER 2008 standard 64 细节事项
- hdu3081 最大流
- Jplayer学习
- python中文件读取模式
- Debian安装配置nginx,php,mysql,wordpress教程
- 图像处理之K-Means算法演示
- Installing MySQL Server on Debian
- Linux 接口地址的获取-暨获取本地IP地址(所有地址,包括IPv4,IPV6,MAC 地址)
- Reverse a Road 最短路
- solr查询参数使用说明