• 【网络流24题 #04】魔术球问题


    题目链接:魔术球问题

    蒟蒻认为本题的关键还是在一个边与点的关系

    本题一看就是图论…当然不少人(包括蒟蒻 是学习网络流来的…

    显然我们要对球或杆进行操作

    由于关系的建立条件是球的相邻放置条件

    所以以球为元素建图 而一个杆子就是一条从起点到终点的路径

    那么 最多能放的杆子数就是最小路径覆盖数

    但是网络流维护的是边的关系

    所以我们使用点拆边技能

    把入度边和出度边分两个点存 然后在这两个点中间连一条路

    注:公式:最小路径覆盖数=点数-最大匹配数

    问题是题目给的是柱子数啊!

    然鹅 对于能放的球数增加 柱子的数量单调增

    因为球从下向上放 能放的球多了柱子数不可能减啊

    debug中的错误:

    1.    S,T定太小 冲突  数组定太小

    2.    反向边初始容量为0

    3.    把next定成bool型。。。

     1 int main(){
     2     scanf("%d", &n);
     3     int cnt = 0, now = 0;
     4     memset(head, -1, sizeof(head));
     5     memset(next, -1, sizeof(next));
     6     S = N - 3, T = N - 2;
     7     while(cnt <= n){
     8         now++;
     9         addedge(S, now << 1, 1); addedge(now << 1 | 1, T, 1);
    10         for(int i = sqrt(now) + 1; i * i < (now << 1); i++)
    11             addedge((i * i - now) << 1, now << 1 | 1, 1);
    12         if(!dinic()) ub[++cnt] = now;     
    13     }
    14     printf("%d
    ", --now);
    15     for(int i = 1; i <= now; i++){
    16         if(!vis[i]){
    17             int k = i;
    18             while(k < (S >> 1) && k != -1 && !vis[k]){
    19                 printf("%d ", k);
    20                 vis[k] = 1;
    21                 k = next[k];
    22             }
    23             printf("
    ");
    24         }
    25     }
    26     return 0;    
    27 }
    关键部分
     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <queue>
     4 #include <cstring>
     5 #include <cmath>
     6 using namespace std;
     7 const int N = 1e6 + 5;
     8 const int inf = 0x3f3f3f3f;
     9 int n;
    10 struct Edge{
    11     int u, v, w, next;
    12 }edge[N << 1];
    13 int head[N], esize = -1;
    14 bool vis[N];
    15 int next[N];
    16 int ub[N];
    17 inline void addedge(int x, int y, int z){
    18     edge[++esize] = (Edge){x, y, z, head[x]};
    19     head[x] = esize;
    20     edge[++esize] = (Edge){y, x, 0, head[y]};
    21     head[y] = esize;
    22 }
    23 queue<int> q;
    24 int dep[N];
    25 int S, T;
    26 
    27 bool bfs(){
    28     int fro;
    29     q.push(S); 
    30     memset(dep, 0, sizeof(dep));
    31     dep[S] = 1;
    32     while(!q.empty()){
    33         fro = q.front(); q.pop();
    34         for(int i = head[fro]; i != -1; i = edge[i].next){
    35             int vv = edge[i].v;
    36             if(!dep[vv] && edge[i].w > 0){
    37                 dep[vv] = dep[fro] + 1;
    38                 q.push(vv);
    39             }
    40         }
    41     }
    42     return dep[T];
    43 }
    44 
    45 int dfs(int x, int rest){
    46     if(x == T || !rest) return rest;
    47     for(int i = head[x], vv, ww, d; i != -1; i = edge[i].next){
    48         vv = edge[i].v, ww = edge[i].w;
    49         if(dep[vv] != dep[x] + 1) continue;
    50         d = dfs(vv, min(rest, ww));
    51         if(d > 0){
    52             edge[i].w -= d;
    53             edge[i ^ 1].w += d;
    54             next[x >> 1] = (vv >> 1);
    55             return d;
    56         }
    57     }
    58     return 0;
    59 }
    60 
    61 bool dinic(){
    62     int ret = 0;
    63     while(bfs())
    64         ret += dfs(S, inf);
    65     return ret;
    66 }
    67 
    68 int main(){
    69     scanf("%d", &n);
    70     int cnt = 0, now = 0;
    71     memset(head, -1, sizeof(head));
    72     memset(next, -1, sizeof(next));
    73     S = N - 3, T = N - 2;
    74     while(cnt <= n){
    75         now++;
    76         addedge(S, now << 1, 1); addedge(now << 1 | 1, T, 1);
    77         for(int i = sqrt(now) + 1; i * i < (now << 1); i++)
    78             addedge((i * i - now) << 1, now << 1 | 1, 1);
    79         if(!dinic()) ub[++cnt] = now;     
    80     }
    81     printf("%d
    ", --now);
    82     for(int i = 1; i <= now; i++){
    83         if(!vis[i]){
    84             int k = i;
    85             while(k < (S >> 1) && k != -1 && !vis[k]){
    86                 printf("%d ", k);
    87                 vis[k] = 1;
    88                 k = next[k];
    89             }
    90             printf("
    ");
    91         }
    92     }
    93     return 0;    
    94 }
    Whole
  • 相关阅读:
    关闭Pinterest通知
    android——创建camera应用(译)
    Android样式——Styles
    Android Fragment学习(一)
    Win32汇编环境配置
    关于微信检测SDK应用的原理浅析(iOS)
    iOS的Mantle实战
    Objective-C运行时的一些技巧
    Autolayout入门教程
    基于RAC的通用TableView
  • 原文地址:https://www.cnblogs.com/hjmmm/p/9277485.html
Copyright © 2020-2023  润新知