• P2765 魔术球问题 (网络流)


    题意:n根柱子 把编号1,2,3....的球依次插到柱子上去

       需要满足相邻的两个球编号加起来为完全平方数 n < 55

    题解:网络流24(23)题里的 

       但是一直不知道怎么建图  或者说建图的意义

       一般都要套路拆点 我的理解就是实际问题背景每个点是需要双向边的 但是网络流算法要建反向边 所以就拆点防止重边 意义更明确

       这个题的话把小球拆点就表示 一个放前面 一个放后面的情况 然后按题意建图 跑最大流

       我最开始以为一条增广路代表一根柱子 其实不是 这里柱子的意义更抽象

       模拟一下程序后发现 在依次加球的过程中 最大流跑通表示的是这个球可以直接接在当前安排方式的后面

       如果跑不通 就要新开柱子了 同时跑新的最大流也能保证反悔操作

    #include <bits/stdc++.h>
    using namespace std;
    
    int n, cnt, p, num, s, t, maxflow;
    
    struct node {
        int to, nex, val;
    }E[200005];
    int head[4005];
    int cur[4005];
    
    void addedge(int x, int y, int va) {
        E[++cnt].to = y; E[cnt].nex = head[x]; E[cnt].val = va; head[x] = cnt;
        E[++cnt].to = x; E[cnt].nex = head[y]; E[cnt].val = 0; head[y] = cnt;
    }
    
    int dep[4005];
    int to[4005];
    int inque[4005];
    bool bfs() {
        for(int i = 0; i <= num * 2 + 2; i++) cur[i] = head[i], dep[i] = 0x3f3f3f3f, inque[i] = 0;
        dep[s] = 0;
        queue<int> que;
        que.push(s);
        inque[s] = 1;
    
        while(!que.empty()) {
            int u = que.front();
            que.pop();
    
            for(int i = head[u]; i; i = E[i].nex) {
                int v = E[i].to;
                if(E[i].val > 0 && dep[v] > dep[u] + 1) {
                    dep[v] = dep[u] + 1;
                    if(!inque[v]) {
                        inque[v] = 1;
                        que.push(v);
                    }
                }
            }
        }
        if(dep[t] != 0x3f3f3f3f) return true;
        return false;
    }
    
    int vis;
    int dfs(int x, int flow) {
        if(x == t) {
            vis = 1;
            maxflow += flow;
            return flow;
        }
    
        int rflow = 0;
        int used = 0;
        for(int i = cur[x]; i; i = E[i].nex) {
            cur[x] = i;
            int v = E[i].to;
            if(E[i].val > 0 && dep[v] == dep[x] + 1) {
                if(rflow = dfs(v, min(flow - used, E[i].val))) {
                    to[x / 2] = v / 2;
                    used += rflow;
                    E[i].val -= rflow;
                    E[i ^ 1].val += rflow;
                    if(used == flow) break;
                }
            }
        }
        return used;
    }
    
    void dinic() {
        maxflow = 0;
        while(bfs()) {
            vis = 1;
            while(vis) {
                vis = 0;
                dfs(s, 100000000);
            }
        }
    }
    
    int ans[60];
    
    int main() {
        p = num = 0;
        cnt = 1;
        scanf("%d", &n);
        s = 0; t = 1;
        while(p <= n) {
            num++;
            addedge(s, num << 1, 1);
            addedge(num << 1 | 1, t, 1);
            for(int i = sqrt(num) + 1; i * i < 2 * num; i++) {
                addedge((i * i - num) << 1, num << 1 | 1, 1);
            }
    
            dinic();
            if(!maxflow) {
                ans[++p] = num;
            }
        }
        printf("%d
    ", num - 1);
        
        for(int i = 1; i <= n; i++) {
            printf("%d", ans[i]);
            for(int j = ans[i]; to[j]; j = to[j]) printf(" %d", to[j]);
            puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    JS中const的使用
    JS的作用域,闭包的理解
    python中函数的默认参数是空数组
    asp.net 导出 Excel
    asp.net 导出 Excel 身份证格式显示格式问题
    HTML5
    JQuery中checkbox选择器
    JQuery中DOM操作(一)
    PL/SQL 创建用户及权限操作
    PL/SQL 表约束
  • 原文地址:https://www.cnblogs.com/lwqq3/p/11150204.html
Copyright © 2020-2023  润新知