• [CQOI2009]跳舞 网络流


    题面:[CQOI2009]跳舞

    题解:

      首先最大时间不好求,而且数据范围很小,所以我们可以先二分一个最大时间,然后就只需要判断是否可行即可。

      因此我们每二分一个mid,对于每个女生,连s ---> x : mid , x ---> x' : k.对于每个男生,连x ---> t : mid, x' ---> x : k.

      对于每条边,如果为Y,连x ---> y.否则连x' ---> y'.

      其中x和x'分别表示一个人和这个人拆分出来的点。

      为什么这么连?

      对于每个女生,连s ---> x : mid , x ---> x' : k。     其中s ---> x : mid 表示一共要进行mid次,x ---> x' : k表示这mid次中最多可以选k个和不喜欢的人相连。

      对于每个男生,连x ---> t : mid, x' ---> x : k.       同上。

      对于每条边,如果为Y,连x ---> y.否则连x' ---> y'.     如果是Y,说明互相喜欢,所以用原本的点相连,否则说明互相不喜欢,就用拆分出的点相连。因为拆分出的点最多只有k次机会,因此表示的是连向不喜欢的点。

      我一开始是这么想的,但是为了看上去简单一点,对于每个女生,我连了s --- > x : lim - k, s --- > x' : k.

      这样是不对的,因为这样就固定了喜欢的人也最多选lim - k个,而实际上是没有这个限制的。因此我们用x ---> x' : k的方法就可以去掉这个限制,并且可以让它相对动态的分配每次机会,而不是每次固定的只能选lim - k次喜欢的,和强制选k次不喜欢的。

      

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define AC 400
      5 #define ac 40000
      6 #define inf 1000000000
      7 
      8 int n, m, ans, all, sum, s, t, head, tail, x, addflow, k;
      9 int Head[AC], Next[ac], date[ac], haveflow[ac], tot = 1;
     10 int have[AC], c[AC], good[AC], last[AC], q[ac];
     11 char f[AC][AC];
     12 
     13 inline int read()
     14 {
     15     int x = 0;char c = getchar();
     16     while(c > '9' || c < '0') c = getchar();
     17     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
     18     return x;
     19 }
     20 
     21 void init()
     22 {
     23     memset(Head, 0, sizeof(Head));
     24     memset(have, 0, sizeof(have));
     25     memset(c, 0, sizeof(c));
     26     ans = 0, tot = 1;
     27 }
     28 
     29 inline void add(int f, int w, int S)
     30 {
     31     date[++ tot] = w, Next[tot] = Head[f], Head[f] = tot, haveflow[tot] = S;
     32     date[++ tot] = f, Next[tot] = Head[w], Head[w] = tot, haveflow[tot] = 0;
     33     //printf("%d %d : %d
    ", f, w, S);
     34 }
     35 
     36 inline void upmin(int &a, int b){
     37     if(b < a) a = b;
     38 }
     39 
     40 void build(int lim)
     41 {
     42     sum = lim * m;
     43     for(R i = 1; i <= n; i ++) add(s, i, lim), add(i, n + i, k);
     44     for(R i = 1; i <= n; i ++)
     45         for(R j = 1; j <= m; j ++)
     46         {
     47             if(f[i][j] == 'Y') add(i, n + n + j, 1);
     48             else add(n + i, n + n + m + j, 1);
     49         }
     50     for(R i = 1; i <= m; i ++) add(n + n + i, t, lim), add(n + n + m + i, n + n + i, k);
     51 }
     52 
     53 void bfs()
     54 {
     55     head = tail = 0;
     56     q[++ tail] = t, c[t] = 1, have[1] = 1;
     57     while(head < tail)
     58     {
     59         int x = q[++ head];
     60         for(R i = Head[x]; i; i = Next[i])
     61         {
     62             int now = date[i];
     63             if(!c[now] && haveflow[i ^ 1])
     64                 ++ have[c[now] = c[x] + 1], q[++ tail] = now;
     65         }
     66     }
     67     memcpy(good, Head, sizeof(Head));
     68 }
     69 
     70 void aru()
     71 {
     72     while(x != s)
     73     {
     74         haveflow[last[x]] -= addflow;
     75         haveflow[last[x] ^ 1] += addflow;
     76         x = date[last[x] ^ 1];
     77     }
     78     ans += addflow;
     79 }
     80 
     81 void isap()
     82 {
     83     bool done = false;
     84     x = s, addflow = inf;
     85     while(c[s] != all)
     86     {
     87         if(x == t) aru(), addflow = inf;
     88         done = false;
     89         for(R i = good[x]; i; i = Next[i])
     90         {
     91             int now = date[i];
     92             good[x] = i;
     93             if(c[now] == c[x] - 1 && haveflow[i])
     94             {
     95                 done = true, x = now, last[now] = i;
     96                 upmin(addflow, haveflow[i]);
     97                 break;
     98             }
     99         }
    100         if(!done)
    101         {
    102             int go = all - 1;
    103             for(R i = Head[x]; i; i = Next[i])
    104                 if(c[date[i]] && haveflow[i]) upmin(go, c[date[i]]);
    105             if(!(-- have[c[x]])) break;
    106             ++ have[c[x] = go + 1], good[x] = Head[x];
    107             if(x != s) x = date[last[x] ^ 1];
    108         }
    109     }
    110 }
    111 
    112 bool check(int lim)
    113 {
    114     init(), build(lim), bfs(), isap();
    115     if(ans == sum) return true;
    116     else return false;
    117 }
    118 
    119 void half()
    120 {
    121     int l = 0, r = n, mid;
    122     while(l < r)
    123     {
    124         mid = (l + r + 1) >> 1;
    125         if(check(mid)) l = mid;
    126         else r = mid - 1;
    127     }
    128     printf("%d
    ", l);
    129 }
    130 
    131 void pre()
    132 {
    133     n = read(), m = n, k = read();
    134     s = n + n + m + m + 1, t = s + 1, all = t + 5;
    135     for(R i = 1; i <= n; i ++) scanf("%s", f[i] + 1);
    136 }
    137 
    138 int main()
    139 {
    140     freopen("in.in", "r", stdin);
    141     pre();
    142     half();
    143     fclose(stdin);
    144     return 0;
    145 }
    146  
    View Code
  • 相关阅读:
    Element+Vue.js 选择器常用属性
    常用xml头文件
    【链接】调查显示:超20%美国大学生曾花学生贷款投
    Quartz遇到的问题
    List去重
    SpringDataJPA
    IDEA:Error during artifact deployment. See server log for details.详解
    Quartz定时任务
    多线程条件通行工具——CountDownLatch
    多线程同步工具——Lock
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9960651.html
Copyright © 2020-2023  润新知