zoukankan      html  css  js  c++  java
  • P2765 魔术球问题(网络流24题)

    题目描述

    «问题描述:

    假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球。

    (1)每次只能在某根柱子的最上面放球。

    (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。

    试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。

    «编程任务:

    对于给定的n,计算在n根柱子上最多能放多少个球。

    输入输出格式

    输入格式:

    第1 行有1个正整数n,表示柱子数。

    输出格式:

    程序运行结束时,将n 根柱子上最多能放的球数以及相应的放置方案输出。文件的第一行是球数。接下来的n行,每行是一根柱子上的球的编号。

    输入输出样例

    输入样例#1: 复制
    4
    输出样例#1: 复制
    11
    1 8
    2 7 9
    3 6 10
    4 5 11


    这题其实和上一题差不多,不过这个是反正过来的。
    这题需要转化一下
    求对于给定的n,计算在n根柱子上最多能放多少个球。
    一开始无从下手,但是它给了一个条件
    在同一根柱子中,任何2个相邻球的编号之和为完全平方数。
    将他转化为二分图,
    求最大匹配数,
    点数=两点最大匹配数+最小路径覆盖数,
    它给的n就是最小路径覆盖数,网络流跑最大匹配数
    然后点数就出来了
    这里采取的是枚举的方法
    求点数,

    然后就是上代码
      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <vector>
      4 #include <queue>
      5 #include <cstring>
      6 #include <string>
      7 #include <cmath>
      8 #include <map>
      9 using namespace std;
     10 const int maxn = 2e5 + 10;
     11 const int INF = 1e9 + 7;
     12 typedef long long LL;
     13 int st = 0, ed = 4000;
     14 struct node {
     15     int from, to, cap, flow;
     16 };
     17 struct Dinic {
     18     int n, m, s, t;
     19     vector<node>nodes;
     20     vector<int>g[maxn];
     21     int vis[maxn], d[maxn], cur[maxn];
     22     void clearall(int n) {
     23         for (int i = 0 ; i < n ; i++) g[i].clear();
     24         nodes.clear();
     25     }
     26     void clearflow() {
     27         int len = nodes.size();
     28         for (int i = 0 ; i < len ; i++) nodes[i].flow = 0;
     29     }
     30     void add(int from, int to, int cap) {
     31         nodes.push_back((node) {
     32             from, to, cap, 0
     33         });
     34         nodes.push_back((node) {
     35             to, from, 0, 0
     36         });
     37         m = nodes.size();
     38         g[from].push_back(m - 2);
     39         g[to].push_back(m - 1);
     40     }
     41     bool bfs() {
     42         memset(vis, 0, sizeof(vis));
     43         queue<int>q;
     44         q.push(s) ;
     45         d[s] = 0;
     46         vis[s] = 1;
     47         while(!q.empty()) {
     48             int x = q.front();
     49             q.pop();
     50             int len = g[x].size();
     51             for (int i = 0 ; i < len ; i++) {
     52                 node & e = nodes[g[x][i]];
     53                 if (!vis[e.to] && e.cap > e.flow ) {
     54                     vis[e.to] = 1;
     55                     d[e.to] = d[x] + 1;
     56                     q.push(e.to);
     57                 }
     58             }
     59         }
     60         return vis[t];
     61     }
     62     int dfs(int x, int a) {
     63         if (x == t || a == 0  ) return a;
     64         int flow = 0, f, len = g[x].size();
     65         for (int & i = cur[x] ; i < len ; i++) {
     66             node & e = nodes[g[x][i]];
     67             if (d[x] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0 ) {
     68                 e.flow += f;
     69                 nodes[g[x][i] ^ 1].flow -= f;
     70                 flow += f;
     71                 a -= f;
     72                 if (a == 0) break;
     73             }
     74         }
     75         return flow;
     76     }
     77     int maxflow(int a, int b) {
     78         s = a;
     79         t = b;
     80         int flow = 0;
     81         while(bfs()) {
     82             memset(cur, 0, sizeof(cur));
     83             flow += dfs(s, INF) ;
     84         }
     85         return flow;
     86     }
     87     void print(int  u) {
     88         vis[u] = 1;
     89         for (int i = 0 ; i < (int)g[u].size() ; i++ ) {
     90             node & e = nodes[g[u][i]];
     91             if (!vis[e.to] && e.flow == 1 && e.from != st && e.to != ed) {
     92                 printf(" %d", e.to - ed / 2);
     93                 print(e.to - ed / 2);
     94             }
     95         }
     96     }
     97 } f;
     98 int main() {
     99     int n;
    100     scanf("%d", &n);
    101     int flow = 0, num = 0;
    102     while(num - flow <= n ) {
    103         num += 1;
    104         f.add(st, num, 1);
    105         f.add(num + ed / 2, ed, 1);
    106         for (int i = 1 ; i < num ; i++) {
    107             if ((int)sqrt(i + num) == sqrt(i + num)) f.add(i, num + ed / 2, 1);
    108         }
    109         flow += f.maxflow(st, ed);
    110     }
    111     num -= 1;
    112     f.clearall(ed);
    113     f.clearflow();
    114     memset(f.vis, 0, sizeof(f.vis));
    115     for (int i = 1 ; i <= num ; i++) {
    116         f.add(0, i, 1);
    117         f.add(i + ed / 2, ed, 1);
    118         for (int j = 1 ; j < i ; j++) {
    119             if ((int)sqrt(i + j) == sqrt(i + j)) f.add(j, i + ed / 2, 1);
    120         }
    121     }
    122     f.maxflow(st, ed);
    123     printf("%d
    ", num);
    124     memset(f.vis, 0, sizeof(f.vis)) ;
    125     for (int i = 1 ; i <= num ; i++) {
    126         if (!f.vis[i]) {
    127             printf("%d", i);
    128             f.print(i);
    129             printf("
    ");
    130         }
    131     }
    132     return 0;
    133 }



  • 相关阅读:
    js键盘事件以及键盘事件拦截
    JavaScript 延迟加载
    二叉树深度优先 求二叉树最大深度
    css 小知识点:inline/inline-block/line-height
    es6 set
    CSS 水平垂直居中
    js 位运算符
    js 函数重载
    js之单例模式
    js 面向对象 ES5 AND ES6
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/8996915.html
Copyright © 2011-2022 走看看