poj 2112(多重匹配题目)

来源:互联网 发布:久米田康治 知乎 编辑:程序博客网 时间:2024/04/28 09:30

题目链接:http://poj.org/problem?id=2112

题意描述:草地上有n个挤奶机和m只奶牛,分别标号为(1,n,n+1,n+m)给出了n+m中任意两点的距离,其中为表示不能直接到达,现在要求所有奶牛到到挤奶机的中的最长距离最短


分析:因为每头牛都必须和一台挤奶机匹配,那么这很明显一台挤奶机要和头奶牛匹配,问题就转换多重匹配问题,我们可以二分枚举答案,然后判断答案是否满足条件,这样找出满足条件的最小值即为结果,题目给出的是任意两点之间的距离,而我们需要的却是奶牛和挤奶机之间的距离,假设我们已经知道这个距离,那么只要这个距离小于等于我们枚举的当前值时就可以连一条边,因为奶牛和挤奶机可能存在多条路径,所以我们找出奶牛和挤奶机之间的最短路径即可,那么用这个最短路径就可以代表他们之间的所有路径了,因为最小值小于一个值那么就可能 存在解


代码:


#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int inf = 0xfffffff;const int N = 240;int C,n;int g[N][N];int mat[N][35];int vlink[35];int link[35][N];bool vis[35];int scan(int u){for(int v=1;v<=n;v++){if(!vis[v]&&mat[u][v]){vis[v]=true;if(vlink[v]<C){link[v][vlink[v]++]=u;return 1;}for(int j=0;j<vlink[v];j++){if(scan(link[v][j])){link[v][j]=u;return 1;}}}}return 0;}int main (){int m,i,j,k,x;while(scanf("%d%d%d",&n,&m,&C)!=EOF)//n表示机器的个数,m表示牛的头数{for(i=1;i<=n+m;i++)for(j=1;j<=n+m;j++){scanf("%d",&g[i][j]);//0表示不能到达if(g[i][j]==0)g[i][j]=inf;}for(k=1;k<=n+m;k++)for(i=1;i<=n+m;i++)for(j=1;j<=n+m;j++)if(g[i][k]+g[k][j] < g[i][j])g[i][j] = g[i][k]+g[k][j];int high=-1,low=inf;for(i=n+1;i<=n+m;i++)for(j=1;j<=n;j++){if(g[i][j] == inf)continue;if(high < g[i][j])high = g[i][j];if(low > g[i][j])low = g[i][j];}int result=0;while(low <=high){int mid=(low+high)>>1;memset(mat,0,sizeof(mat));for(i=1;i<=m;i++)for(j=1;j<=n;j++)if(g[n+i][j]<=mid)mat[i][j]=1;memset(vlink,0,sizeof(vlink));for(i=1;i<=m;i++){memset(vis,0,sizeof(vis));if(!scan(i))break;}if(i>m){result=mid;high=mid-1;}else low = mid+1;}printf("%d\n",result);}return 0;}