• [CQOI2009]跳舞


    嘟嘟嘟

    因为如果能跳x支舞曲,那么一定能跳y(y < x)支舞曲,满足单调性。因此可二分舞曲。

    那么网络流建图就明白了:把每一个男生拆成3个点,分别是男生总,男生喜欢的,男生不喜欢的。然后从源点向男生总连一条容量为x的边,从男生总向男生喜欢的连一条INF的边,向男生不喜欢的连一条k的边。女生同理。

    然后对于一对互相喜欢的男女生,就从男生喜欢的向女生喜欢的连一条1的边;对于不喜欢的男女生,就从男生不喜欢的向女生不喜欢的连一条1的边。跑一遍最大流,如果总流量等于x * n,就说明可以跳x支舞曲,向上二分。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 50;
     21 inline ll read()
     22 {
     23     ll ans = 0;
     24     char ch = getchar(), last = ' ';
     25     while(!isdigit(ch)) {last = ch; ch = getchar();}
     26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     27     if(last == '-') ans = -ans;
     28     return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32     if(x < 0) x = -x, putchar('-');
     33     if(x >= 10) write(x / 10);
     34     putchar(x % 10 + '0');
     35 }
     36 
     37 int n, k, t;
     38 char a[maxn + 5][maxn + 5];
     39 
     40 struct Edge
     41 {
     42     int from, to, cap, flow;
     43 };
     44 vector<Edge> edges;
     45 vector<int> G[maxn * 6 + 5];
     46 void addEdge(int from, int to, int w)
     47 {
     48     edges.push_back((Edge){from, to, w, 0});
     49     edges.push_back((Edge){to, from, 0, 0});
     50     int sz = edges.size();
     51     G[from].push_back(sz - 2);
     52     G[to].push_back(sz - 1);
     53 }
     54 
     55 int dis[maxn * 6 + 5];
     56 bool bfs()
     57 {
     58     Mem(dis, 0); dis[0] = 1;
     59     queue<int> q; q.push(0);
     60     while(!q.empty())
     61     {
     62         int now = q.front(); q.pop();
     63         for(int i = 0; i < (int)G[now].size(); ++i)
     64         {
     65             Edge& e = edges[G[now][i]];
     66             if(!dis[e.to] && e.cap > e.flow)
     67             {
     68                 dis[e.to] = dis[now] + 1;
     69                 q.push(e.to);    
     70             }
     71         }
     72     }
     73     return dis[t];
     74 }
     75 int cur[maxn * 6 + 5];
     76 int dfs(int now, int res)
     77 {
     78     if(now == t || res == 0) return res;
     79     int flow = 0, f;
     80     for(int& i = cur[now]; i < (int)G[now].size(); ++i)
     81     {
     82         Edge& e = edges[G[now][i]];
     83         if(dis[e.to] == dis[now] + 1 && (f = dfs(e.to, min(res, e.cap - e.flow))) > 0)
     84         {
     85             e.flow += f;
     86             edges[G[now][i] ^ 1].flow -= f;
     87             flow += f; res -= f;
     88             if(res == 0) break;
     89         }
     90     }
     91     return flow;
     92 }
     93 
     94 int maxflow()
     95 {
     96     int flow = 0;
     97     while(bfs())
     98     {
     99         Mem(cur, 0);
    100         flow += dfs(0, INF);
    101     }
    102     return flow;
    103 }
    104 
    105 void build_Gra(int x)        //暴力重构 
    106 {
    107     edges.clear();            
    108     for(int i = 0; i <= t; ++i) G[i].clear();
    109     for(int i = 1; i <= n; ++i)
    110     {
    111         addEdge(0, i, x);
    112         addEdge(i, n + i, INF); 
    113         addEdge(i, (n << 1) + i, k);
    114         addEdge(n * 5 + i, t, x); 
    115         addEdge((n << 1) + n + i, n * 5 + i, INF);
    116         addEdge((n << 2) + i, n * 5 + i, k);
    117         for(int j = 1; j <= n; ++j) 
    118         {
    119             if(a[i][j] == 'Y') addEdge(n + i, (n << 1) + n + j, 1);
    120             else addEdge((n << 1) + i, (n << 2) + j, 1); 
    121         }
    122     }
    123 }
    124 
    125 int main()
    126 {
    127     n = read(); k = read();
    128     t = (n << 2) + (n << 1) + 1;
    129     for(int i = 1; i <= n; ++i) scanf("%s", a[i] + 1);
    130     int L = 0, R = n;
    131     while(L < R)
    132     {
    133         int mid = (L + R + 1) >> 1;
    134         build_Gra(mid);
    135         if(maxflow() == mid * n) L = mid;
    136         else R = mid - 1;
    137     }
    138     write(L); enter;
    139     return 0;
    140 }
    View Code
  • 相关阅读:
    阿里Canal中间件的初步搭建和使用
    深入理解Java String类
    深入理解Java中的String
    Docker 容器数据卷(挂载)
    在docker容器下利用数据卷实现在删除了mysql容器或者镜像的情况下恢复数据
    EFK(Elasticsearch+Filebeat+Kibana)收集容器日志
    Docker 容器日志占用空间过大解决办法
    四种软件架构,看看你属于哪个层次
    Kubernetes 如何只授予某一 Namespace 的访问权限
    Docker实验Docker的网络配置
  • 原文地址:https://www.cnblogs.com/mrclr/p/9700648.html
Copyright © 2020-2023  润新知