• 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         
  • 相关阅读:
    python操作word
    python安装pyautogui时遇到Pillow问题
    python中弹出消息框--MessageBox( pywin32)
    python 正则匹配汉字、简单读写、打开txt文件
    安装node(淘宝镜像)+Vue-cli+element-ui逐步搭建开发环境
    MT【317】两次判别式
    MT【316】常数变易法
    MT【315】勾股数
    MT【314】正切比值
    MT【313】特征方程逆用
  • 原文地址:https://www.cnblogs.com/wally/p/3059703.html
Copyright © 2020-2023  润新知