poj 2112 最大流求二分图匹配/二分搜索
来源:互联网 发布:安阳市网络教育平台 编辑:程序博客网 时间:2024/05/17 06:46
#include<cstdio>#include<cstring>#include<string.h>#include<vector>#include<queue>#include<iostream>#include<algorithm>#define INF 0x3f3f3fusing namespace std;const int maxn=310;int c,m,k;struct edge{int to,cap,rev;};vector<edge> G[maxn];int level[maxn];int iter[maxn];int dis[maxn][maxn];void addEdge(int from,int to,int cap){ G[from].push_back((edge){to,cap,G[to].size()}); G[to].push_back((edge){from,0,G[from].size()-1});}void bfs(int s){ memset(level,-1,sizeof(level)); queue<int> que; level[s]=0; que.push(s); while(!que.empty()) { int v=que.front(); que.pop(); for(int i=0;i<G[v].size();i++){ edge &e=G[v][i]; if(e.cap>0&&level[e.to]<0) { level[e.to]=level[v]+1; que.push(e.to); } } }}int dfs(int v,int t,int f){ if(v==t) return f; for(int &i=iter[v];i<G[v].size();i++) { edge &e =G[v][i]; if(e.cap>0&&level[v]<level[e.to]) { int d=dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0;}int maxFlow(int s,int t){ int flow=0; for(;;) { bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,INF))>0) {flow+=f;} }}void build(int x){ for(int i=1;i<=k;i++) addEdge(i,k+c+1,m); for(int j=k+1;j<=k+c;j++) addEdge(0,j,1); for(int j=k+1;j<=k+c;j++) for(int i=1;i<=k;i++) if(dis[j][i]<=x)///建图时要弄清楚出发点和终点 { addEdge(j,i,1); }}int main(){ while(scanf("%d%d%d",&k,&c,&m)!=EOF) { //memset(iter,0,sizeof(iter)); //memset(level,0,sizeof(level)); memset(dis,0,sizeof(dis)); for(int i=1;i<=k+c;i++) for(int j=1;j<=k+c;j++) {scanf("%d",&dis[i][j]); if(dis[i][j]==0) dis[i][j]=INF;} for(int l=1;l<=k+c;l++) for(int i=1;i<=k+c;i++) for(int j=1;j<=k+c;j++) if(dis[i][j]>dis[i][l]+dis[l][j]) dis[i][j]=dis[i][l]+dis[l][j]; int L=0,R=100000,mid; int tp; while(L<R){/// 二分枚举 max_min mid=(L+R)>>1; for(int i=0;i<=310;i++)///一定要记得清空vector G[i].clear(); build(mid); tp=maxFlow(0,c+k+1);///二分图中tp(最大流)为最大匹配 //cout<<tp<<endl; if(tp>=c) {R=mid;} else {L=mid+1;} }///二分建图枚举,最大流最小值。 printf("%d\n",R); } return 0;}
相似的一题是UVA753(算法入门)
#include <cstdio>#include <cstring>#include <queue>using namespace std;#define INF 0x3f3f3f3f#define MAXN 250#define MAXM 40100int N,M,K,CNT,edgenum,first[MAXN],mat[MAXN],vis[MAXN],cov[MAXN];struct edge{ int u,v,next;}e[MAXM];struct device //电器{ char s1[30],s2[30];}d[MAXN];struct adapter //转换器{ char s1[30], s2[30];}a[MAXN];struct receptacle //插座{ char s[30];}r[MAXN]; void add(int u , int v){ e[edgenum].u=u; e[edgenum].v=v; e[edgenum].next=first[u]; first[u]=edgenum++;}int dfs(int j , int k) //目标是j插座,当前是k转换器{ if(!strcmp(a[k].s2 , r[j].s)) //当前转换器能插入插座中 return 1; vis[k]=1; //标记k转换器被用过,在一趟dfs中一种转换器没必要被用两次 for(int i=1; i<=K; i++) if(!vis[i]) //所有没被用过的转换器 if(!strcmp(a[k].s2 , a[i].s1)) {//另外k转换器可以插入i转换器中 if(dfs(j,i)) return 1; vis[i]=0; } return 0;}int find(int i , int j) //i电器和j插座{ memset(vis,0,sizeof(vis)); for(int k=1; k<=K; k++) //所有转换器 if(!strcmp(d[i].s2 , a[k].s1)) {//电器能插入转换器的入口 if(dfs(j,k)) return 1; vis[k]=0; } return 0;}void input(){ scanf("%d",&N); for(int i=1; i<=N; i++) scanf("%s",r[i].s); scanf("%d",&M); for(int i=1; i<=M; i++) scanf("%s%s",d[i].s1,d[i].s2); scanf("%d",&K); for(int i=1; i<=K; i++) scanf("%s%s",a[i].s1,a[i].s2); CNT=N+M+K;}void init(){ memset(first,-1,sizeof(first)); edgenum=0; for(int i=1; i<=M; i++) //所有电器 for(int j=1; j<=N; j++) //所有插座 { if(!strcmp(d[i].s2 , r[j].s)) //可以直接相连 { //printf("直接相连%d---%d\n",i,j); add(i,j+M); //建立有向边 } else if(find(i,j)) //如果通过转换器能连接上 { //printf("通过转换器连接%d---%d\n",i,j); add(i,j+M); } }}void printfff(){ for(int i=0; i<edgenum; i++) printf("%d %d %d\n",e[i].u,e[i].v,e[i].next);}int dfs_match(int u){ for(int k=first[u]; k!=-1; k=e[k].next) { int v=e[k].v; if(!cov[v]) { cov[v]=1; if( mat[v]==-1 || dfs_match(mat[v]) ) { mat[v]=u; return 1; } } } return 0;}void maxmatch(){ int max=0; memset(mat,-1,sizeof(mat)); for(int i=1; i<=M+N; i++) //所有的点都做一次起点 { memset(cov,0,sizeof(cov)); max+=dfs_match(i); } //for(int i=1; i<=M+N; i++) //printf("%d<--->%d\n",i,mat[i]); //printf("max=%d\n",max); printf("%d\n",M-max);}int main(){ int T; scanf("%d",&T); while(T--) { input(); init(); //printfff(); maxmatch(); if(T) printf("\n"); } return 0;}
两题对比来看,都是二分图匹配问题。
阅读全文
0 0
- poj 2112 最大流求二分图匹配/二分搜索
- 求二分图最大匹配
- 求二分图最大匹配
- POJ-1087 二分图匹配,最大流。
- POJ 2112 Optimal Milking 二分图最大匹配+二分答案
- POJ 2536 Gopher II (二分图求最大匹配)
- Poj 2112 [最大流] [二分图的多重匹配]
- POJ 2112 Optimal Milking (二分+最短路+最大流or二分图多重匹配)
- POJ 2112 Optimal Milking(最大流+Floyd+二分||二分图匹配)
- POJ 2112 Optimal Milking 二分+二分图多重匹配,网络最大流
- 排座位 二分图最大匹配 搜索
- 二分图求最大匹配,匈牙利
- 【hdu2444】判断二分图+求最大匹配
- 匈牙利算法 求二分图最大匹配
- hdu 2444 二分图判定+求二分图最大匹配
- poj 2226 最大流二分匹配
- POJ 1274 二分图最大匹配
- POJ 1469 二分图最大匹配
- LightOJ 1128 Greatest Parent
- mybaits(3)_使用注解进行增删改查
- 随机抽题考试程序
- Java实现验证码制作
- javabean注意事项之用Integer替换你的int
- poj 2112 最大流求二分图匹配/二分搜索
- 读者写者问题
- The more, The Better HDU
- RabbitMQ系列教程之七:RabbitMQ的 C# 客户端 API 的简介
- 【C语言】查询算法
- 删除大数量的表中数据之存储过程模板
- Wormholes
- glib-The Main Event Loop
- 素数的一些逻辑题