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

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

    思路:3081差不多,就是多了每个女孩可以另外选任意k个不喜欢的,将每个女孩u分为u1,u2,若u喜欢v则加一条u1到v的边 否则加一条u2到v的边,令加u1到u2的容量为k的边;

    然后不知道为什么,wa了一下午,哎。。。

    以下是wa代码,不知道哪儿有bug.

    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 using namespace std;
      5 #define MAXM 22222222
      6 #define MAXN 888
      7 #define inf 1<<30
      8 struct Edge{
      9     int v,cap,next;
     10 }edge[MAXM],E[MAXM];
     11 
     12 int map[MAXN][MAXN];
     13 int cur[MAXN];
     14 int head[MAXN];
     15 int pre[MAXN];
     16 int level[MAXN];
     17 int gap[MAXN];
     18 int NV,NE,n,m,k,f;
     19 int parent[MAXN];
     20 int girl[MAXN],boy[MAXN];
     21 
     22 
     23 void Initiate(){
     24     for(int i=1;i<=n;i++){
     25         parent[i]=-1;
     26     }
     27 }
     28 
     29 
     30 int Find(int x){
     31     int s;
     32     for(s=x;parent[s]>0;s=parent[s])
     33         ;
     34     while(x!=s){
     35         int tmp=parent[x];
     36         parent[x]=s;
     37         x=tmp;
     38     }
     39     return s;
     40 }
     41 
     42 void Union(int u,int v){
     43     int r1=Find(u);
     44     int r2=Find(v);
     45     if(r1==r2)return ;
     46     if(parent[r1]>parent[r2]){
     47         parent[r2]+=parent[r1];
     48         parent[r1]=r2;
     49     }else {
     50         parent[r1]+=parent[r2];
     51         parent[r2]=r1;
     52     }
     53 }
     54 
     55 
     56 /*
     57 int Find(int x){
     58     return parent[x]==x?x:(parent[x]=Find(parent[x]));
     59 }
     60 
     61 void Union(int u,int v){
     62     int r1=Find(u);
     63     int r2=Find(v);
     64     if(r1!=r2){
     65         r1<r2?parent[r2]=r1:parent[r1]=r2;
     66     }
     67 }
     68 */
     69 
     70 
     71 int SAP(int vs,int vt){
     72     memset(pre,-1,sizeof(pre));
     73     memset(level,0,sizeof(level));
     74     memset(gap,0,sizeof(gap));
     75     for(int i=0;i<=3*n+1;i++)cur[i]=head[i];
     76     int u=pre[vs]=vs,maxflow=0,aug=-1;
     77     gap[0]=NV;
     78     while(level[vs]<NV){
     79 loop:
     80         for(int &i=cur[u];i!=-1;i=edge[i].next){
     81             int v=edge[i].v;
     82             if(edge[i].cap&&level[u]==level[v]+1){
     83                 aug==-1?aug=edge[i].cap:(aug=min(aug,edge[i].cap));
     84                 pre[v]=u;
     85                 u=v;
     86                 if(v==vt){
     87                     maxflow+=aug;
     88                     for(u=pre[u];v!=vs;v=u,u=pre[u]){
     89                         edge[cur[u]].cap-=aug;
     90                         edge[cur[u]^1].cap+=aug;
     91                     }
     92                     aug=-1;
     93                 }
     94                 goto loop;
     95             }
     96         }
     97         int minlevel=NV;
     98         for(int i=head[u];i!=-1;i=edge[i].next){
     99             int v=edge[i].v;
    100             if(edge[i].cap&&minlevel>level[v]){
    101                 cur[u]=i;
    102                 minlevel=level[v];
    103             }
    104         }
    105         gap[level[u]]--;
    106         if(gap[level[u]]==0)break;
    107         level[u]=minlevel+1;
    108         gap[level[u]]++;
    109         u=pre[u];
    110     }
    111     return maxflow;
    112 }
    113 
    114 void Insert(int u,int v,int cap,int cc=0){
    115     edge[NE].v=v;edge[NE].cap=cap;
    116     edge[NE].next=head[u];head[u]=NE++;
    117 
    118     edge[NE].v=u;edge[NE].cap=cc;
    119     edge[NE].next=head[v];head[v]=NE++;
    120 }
    121 
    122 void Build(int cap){
    123     for(int i=0;i<NE;i++){
    124         edge[i]=E[i];
    125     }
    126     for(int i=0;i<4*n;i++){
    127         edge[i].cap=cap;
    128     }
    129 }
    130 
    131 
    132 int Binary_Search(){
    133     int low=0,high=n,tmp=0;
    134     NV=3*n+2;
    135     while(low<=high){
    136         int mid=(low+high)>>1;
    137         Build(mid);
    138         if(mid*n==SAP(0,3*n+1)){
    139             tmp=mid;
    140             low=mid+1;
    141         }else
    142             high=mid-1;
    143     }
    144     return tmp;
    145 }
    146 
    147 
    148 int main(){
    149     int _case,g,b,g1,g2;
    150     scanf("%d",&_case);
    151     while(_case--){
    152         scanf("%d%d%d%d",&n,&m,&k,&f);
    153         Initiate();
    154         //for(int i=1;i<=n;i++)parent[i]=i;
    155         memset(map,0,sizeof(map));
    156         memset(head,-1,sizeof(head));
    157         for(int i=1;i<=m;i++){
    158             scanf("%d%d",&girl[i],&boy[i]);
    159         }
    160         for(int i=1;i<=f;i++){
    161             scanf("%d%d",&g1,&g2);
    162             Union(g1,g2);
    163         }
    164         for(int i=1;i<=m;i++){map[Find(girl[i])][boy[i]]=1;}
    165         for(int i=1;i<=n;i++){
    166             for(int j=1;j<=n;j++){
    167                 if(map[Find(i)][j]==1)map[i][j]=1;
    168             }
    169         }
    170         NE=0;
    171         for(int i=1;i<=n;i++){
    172             Insert(0,i,1);//源点与女孩之间添边
    173         }
    174         for(int i=2*n+1;i<=3*n;i++){
    175             Insert(i,3*n+1,1);//男孩与汇点之间连边
    176         }
    177         //将每个女孩拆成i,i+n;
    178         for(int i=1;i<=n;i++){
    179             Insert(i,i+n,k);//女孩与女孩之间加边
    180         }
    181         for(int i=1;i<=n;i++){
    182             for(int j=1;j<=n;j++){
    183                 if(map[i][j]){    
    184                     Insert(i,j+2*n,1);//如果女孩和男孩连边,则i与男孩连边
    185                 }else {
    186                     Insert(i+n,j+2*n,1);//没有边,则i+n与男孩连边
    187                 }
    188             }
    189         }
    190         for(int i=0;i<NE;i++)E[i]=edge[i];
    191         int ans=Binary_Search();
    192         printf("%d\n",ans);
    193     }
    194     return 0;
    195 }
    196 
    197 
    198 
    199 
    200 
    201         
  • 相关阅读:
    2018 ACM 网络选拔赛 徐州赛区
    2018 ACM 网络选拔赛 焦作赛区
    2018 ACM 网络选拔赛 沈阳赛区
    poj 2289 网络流 and 二分查找
    poj 2446 二分图最大匹配
    poj 1469 二分图最大匹配
    poj 3249 拓扑排序 and 动态规划
    poj 3687 拓扑排序
    poj 2585 拓扑排序
    poj 1094 拓扑排序
  • 原文地址:https://www.cnblogs.com/wally/p/3059703.html
Copyright © 2011-2022 走看看