zoukankan      html  css  js  c++  java
  • hdu 3081(二分+最大流+并查集)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081

    思路设源点为0,汇点为2*n+1,对没吵过架的女生和男生连容量为1的边(这里要用到并查集,每个女生的朋友也可以和该男生连边),然后就是源点与女生连边,容量为mid(0<=mid<=n),男生与汇点也连容量为mid的边(这里的mid即为为每个男孩和女孩找到了k个不同的伴侣,说明游戏可以进行k轮,附上链接:http://blog.csdn.net/qq564690377/article/details/7857983),然后就是二分搜索了。

    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 using namespace std;
      5 #define MAXN 222
      6 #define inf 1<<30
      7 int map[MAXN][MAXN];
      8 int mm[MAXN][MAXN];
      9 int pre[MAXN];
     10 int level[MAXN];
     11 int gap[MAXN];
     12 int parent[MAXN];
     13 int NV,n,m,f;
     14 
     15 void Initiate(){
     16     for(int i=1;i<=2*n;i++){
     17         parent[i]=-1;
     18     }
     19 }
     20 
     21 int Find(int x){
     22     int s;
     23     for(s=x;parent[s]>0;s=parent[s])
     24         ;
     25     while(x!=s){
     26         int tmp=parent[x];
     27         parent[x]=s;
     28         x=tmp;
     29     }
     30     return s;
     31 }
     32 
     33 void Union(int u,int v){
     34     int r1=Find(u);
     35     int r2=Find(v);
     36     if(r1==r2)return ;
     37     if(parent[r1]>parent[r2]){
     38         parent[r2]+=parent[r1];
     39         parent[r1]=r2;
     40     }else {
     41         parent[r1]+=parent[r2];
     42         parent[r2]=r1;
     43     }
     44 }
     45 
     46 
     47 int SAP(int vs,int vt){
     48     memset(pre,-1,sizeof(pre));
     49     memset(level,0,sizeof(level));
     50     memset(gap,0,sizeof(gap));
     51     int v,u=pre[vs]=vs,maxflow=0,aug=inf;
     52     gap[0]=NV;
     53     while(level[vs]<NV){
     54         for(v=1;v<=vt;v++){
     55             if(map[u][v]&&level[u]==level[v]+1){
     56                 break;
     57             }
     58         }
     59         if(v<=vt){
     60             pre[v]=u;
     61             u=v;
     62             if(v==vt){
     63                 aug=inf;
     64                 for(int i=v;i!=vs;i=pre[i]){
     65                     if(aug>map[pre[i]][i])aug=map[pre[i]][i];
     66                 }
     67                 maxflow+=aug;
     68                 for(int i=v;i!=vs;i=pre[i]){
     69                     map[pre[i]][i]-=aug;
     70                     map[i][pre[i]]+=aug;
     71                 }
     72                 u=vs;
     73             }
     74         }else {
     75             int minlevel=NV;
     76             for(int v=1;v<=vt;v++){
     77                 if(map[u][v]&&minlevel>level[v]){
     78                     minlevel=level[v];
     79                 }
     80             }
     81             gap[level[u]]--;
     82             if(gap[level[u]]==0)break;
     83             level[u]=minlevel+1;
     84             gap[level[u]]++;
     85             u=pre[u];
     86         }
     87     }
     88     return maxflow;
     89 }
     90 
     91 void Build(int k){
     92     memset(map,0,sizeof(map));
     93     for(int i=1;i<=n;i++){
     94         map[0][i]=k;
     95         map[i+n][2*n+1]=k;
     96     }
     97     for(int i=1;i<=n;i++){
     98         for(int j=n+1;j<=2*n;j++){
     99             map[i][j]=mm[i][j];
    100         }
    101     }
    102     for(int i=1;i<=n;i++){
    103         for(int j=1;j<=n;j++){
    104             if(Find(i)==Find(j)){
    105                 for(int k=n+1;k<=2*n;k++){
    106                     if(map[i][k])map[j][k]=1;
    107                 }
    108             }
    109         }
    110     }
    111 }
    112 
    113 
    114 int Binary_Search(){
    115     int low=0,high=n,tmp;
    116     NV=2*n+2;
    117     while(low<=high){
    118         int mid=(low+high)/2;
    119         Build(mid);
    120         if(mid*n==SAP(0,2*n+1)){
    121             tmp=mid;//这里需要保留mid值。
    122             low=mid+1;
    123         }else 
    124             high=mid-1;
    125     }
    126     return tmp;
    127 }
    128 
    129 
    130 int main(){
    131     int _case,g,b,g1,g2;
    132     scanf("%d",&_case);
    133     while(_case--){
    134         scanf("%d%d%d",&n,&m,&f);
    135         Initiate();
    136         memset(map,0,sizeof(map));
    137         memset(mm,0,sizeof(mm));
    138         for(int i=1;i<=m;i++){
    139             scanf("%d%d",&g,&b);
    140             map[g][b+n]=1;
    141             mm[g][b+n]=1;//保留原图,因为每次SAP之后,图就改变了。
    142         }
    143         for(int i=1;i<=f;i++){
    144             scanf("%d%d",&g1,&g2);
    145             if(Find(g1)!=Find(g2)){
    146                 Union(g1,g2);
    147             }
    148         }
    149         int ans=Binary_Search();
    150         printf("%d\n",ans);
    151     }
    152     return 0;
    153 }
    154 
    155         
    156 
    157 
    158 
    159             
  • 相关阅读:
    第二十章 数据访问(In .net4.5) 之 使用LINQ
    第十九章 数据访问(In .net4.5) 之 处理数据
    第十八章 数据访问(In .net4.5) 之 I/O操作
    第十七章 调试及安全性(In .net4.5) 之 程序诊断
    大叔学Spring Boot笔记(14)A component required a bean of type '...Mapper' that could not be found问题解决
    大叔学Spring Boot笔记(13)Free Mybatis plugin使用
    MySQL查询结果中Duration Time和Fetch Time的区别
    大叔学Spring Boot笔记(12)Windows环境下使用bat启动和停止Java【转】
    大叔学Spring Boot笔记(11)jdk/bin目录下的不同exe文件的用途及区别【转】
    大叔学Spring Boot笔记(十)手动编译、打包并运行项目
  • 原文地址:https://www.cnblogs.com/wally/p/3059095.html
Copyright © 2011-2022 走看看