zoukankan      html  css  js  c++  java
  • 【HUST 1024 】 拆点+二分枚举可行流

    题目链接:http://acm.hust.edu.cn/problem.php?id=1024

    题目大意:有n个男孩和n个女孩参加party,现在让你将他们分成n对不同的舞伴(只能男和女),男孩女孩可以和自己喜欢的人,最多和k个自己不喜欢的异性配对,现在问你能跳多少次舞(n对配完一次跳一次舞,每次的舞伴都不能重复)。

    解题思路:  网络流,关键在于建图。

                   把男性拆成两个点,分别放置在两个集合内,Xa和Xb,女性拆成两个点,分别放置在Ya和Yb内。Xa到Xb连接一条有向边,权值为k,Yb到Ya连接一条有向边,权值为k。当boy喜欢girl时,Xa和Ya之间连接一条对应的有向边权值为1,当boy不喜欢girl时,Xb和Yb连接一条对应的有向边,权值为1。

                 最后二分枚举可行解ans, 超级源点到Xa的每个点连接一条有向边,权值为ans,Ya内的每个点和超级汇点连接一条有向边,权值也为ans。最后流啊流,最大流满足max_flow==n*ans时,继续二分,直到找到最优解。

                这里要注意的是用一个tmp数组保存每条边的起始容量。

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 using namespace std;
      6 
      7 const int mn=1024;
      8 const int mm=1000000;
      9 const int oo=0x3fffffff;
     10 int node, st, sd, edge;
     11 int flow[mm], reach[mm], next[mm], tmp[mm];
     12 int head[mn], work[mn], dis[mn], que[mn];
     13 int map[110][110];
     14 
     15 void init(int node_, int st_, int sd_)
     16 {
     17     node=node_, st=st_, sd=sd_;
     18     for(int i=0; i<node; i++) head[i]=-1;
     19     edge=0;
     20 }
     21 
     22 void addedge(int u, int v, int c1, int c2)
     23 {
     24     reach[edge]=v, flow[edge]=c1, tmp[edge]=c1, next[edge]=head[u], head[u]=edge++;
     25     reach[edge]=u, flow[edge]=c2, tmp[edge]=c2, next[edge]=head[v], head[v]=edge++;
     26 }
     27 
     28 bool bfs()
     29 {
     30     int u, v, l=0, h=0;
     31     for(int i=0; i<node; i++) dis[i]=-1;
     32     que[l++]=st;
     33     dis[st]=0;
     34     while(l!=h)
     35     {
     36         u=que[h++];
     37         if(h==mn) h=0;
     38         for(int i=head[u]; i>=0; i=next[i])
     39         {
     40             v=reach[i];
     41             if(flow[i]&&dis[v]<0)
     42             {
     43                 dis[v]=dis[u]+1;
     44                 que[l++]=v;
     45                 if(l==mn) l=0;
     46                 if(v==sd) return true;
     47             }
     48         }
     49     }
     50     return false;
     51 }
     52 
     53 int dfs(int u, int exp)
     54 {
     55     if(u==sd) return exp;
     56     for(int &i=work[u]; i>=0; i=next[i])
     57     {
     58         int v=reach[i], tp;
     59         if(flow[i]&&dis[v]==dis[u]+1&&(tp=dfs(v,min(flow[i],exp))>0))
     60         {
     61             flow[i]-=tp;
     62             flow[i^1]+=tp;
     63             return tp;
     64         }
     65     }
     66     return 0;
     67 }
     68 
     69 int Dinic()
     70 {
     71     int max_flow=0, flow;
     72     while(bfs())
     73     {
     74         for(int i=0; i<node; i++) work[i]=head[i];
     75         while(flow=dfs(st,oo)) max_flow+=flow;
     76     }
     77     return max_flow;
     78 }
     79 
     80 void Update(int mid)
     81 {
     82     for(int i=0; i<edge; i++) flow[i]=tmp[i];
     83     for(int i=head[st]; i>=0; i=next[i])
     84     {
     85         flow[i]=mid;
     86         flow[i^1]=0;
     87     }
     88     for(int i=head[sd]; i>=0; i=next[i])
     89     {
     90         flow[i]=0;
     91         flow[i^1]=mid;
     92     }
     93 }
     94 
     95 int main()
     96 {
     97     int T, n, m, k;
     98     cin >> T;
     99     while(T--)
    100     {
    101         cin >> n >> m >> k;
    102         init(4*n+2,0,4*n+1);
    103         memset(map,0,sizeof(map));
    104         while(m--)
    105         {
    106             int u, v;
    107             scanf("%d%d",&u,&v);
    108             map[u][v]=1;
    109         }
    110         for(int i=1; i<=n; i++)
    111             for(int j=1; j<=n; j++)
    112             {
    113                   if(map[i][j])  addedge(i,3*n+j,1,0);
    114                   else addedge(n+i,2*n+j,1,0);
    115             }
    116         for(int i=1; i<=n; i++)
    117         {
    118             addedge(st,i,0,0);
    119             addedge(3*n+i,sd,0,0);
    120             addedge(i,n+i,k,0);
    121             addedge(2*n+i,3*n+i,k,0);
    122         }
    123         int l=0, r=n, mid, ans=0;
    124         while(l<=r)
    125         {
    126             mid=(l+r)>>1;
    127             Update(mid);
    128             if(Dinic()==n*mid)
    129             {
    130                 ans=mid;
    131                 l=mid+1;
    132             }
    133             else r=mid-1;
    134         }
    135         cout << ans <<endl;
    136     }
    137     return 0;
    138 }
  • 相关阅读:
    PhpStorm 配置IDE
    PhpStorm 配置数据库
    将EXCEL表中的数据轻松导入Mysql数据表
    JavaScript Map数据结构
    JavaScript RegExp 对象
    JavaScriptDate(日期)
    JavaScript 对象
    JavaScript 闭包
    JavaScript 函数调用
    JavaScript 函数参数
  • 原文地址:https://www.cnblogs.com/kane0526/p/2978705.html
Copyright © 2011-2022 走看看