zoukankan      html  css  js  c++  java
  • [BJOI2012] 连连看

    Description

    给出一个闭区间 ([a,b]) 中的全部整数,如果其中某两个数 (x)(y)(x > y))的平方差 (x^2-y^2) 是一个完全平方数 (z^2),并且 (y)(z) 互质,那么就可以将 (x)(y) 连起来并且将它们一起消除,同时得到 (x+y) 点分数。消除的数对尽可能多的前提下,得到足够的分数。(a,b le 1000)

    Solution

    关键是要通过正反建边来保证数字不会被重复使用,最终结果除以 2 即可

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    // Init: init() !!!!!
    // Input: make(u,v,cap,cost)
    // Solver: solve(s,t)
    // Output: ans, cost
    namespace flow {
    const int N = 100005;
    const int M = 1000005;
    const int inf = 1e+12;
    struct Edge {
        int p, c, w, nxt = -1;
    } e[N];
    int s, t, tans, ans, cost, ind, bus[N], qhead = 0, qtail = -1, qu[M],vis[N], dist[N];
    
    void graph_link(int p, int q, int c, int w) {
        e[ind].p = q;
        e[ind].c = c;
        e[ind].w = w;
        e[ind].nxt = bus[p];
        bus[p] = ind;
        ++ind;
    }
    void make(int p, int q, int c, int w) {
        graph_link(p, q, c, w);
        graph_link(q, p, 0, -w);
    }
    int dinic_spfa() {
        qhead = 0;
        qtail = -1;
        memset(vis, 0x00, sizeof vis);
        memset(dist, 0x3f, sizeof dist);
        vis[s] = 1;
        dist[s] = 0;
        qu[++qtail] = s;
        while (qtail >= qhead) {
            int p = qu[qhead++];
            vis[p] = 0;
            for (int i = bus[p]; i != -1; i = e[i].nxt)
                if (dist[e[i].p] > dist[p] + e[i].w && e[i].c > 0) {
                    dist[e[i].p] = dist[p] + e[i].w;
                    if (vis[e[i].p] == 0)
                        vis[e[i].p] = 1, qu[++qtail] = e[i].p;
                }
        }
        return dist[t] < inf;
    }
    int dinic_dfs(int p, int lim) {
        if (p == t)
            return lim;
        vis[p] = 1;
        int ret = 0;
        for (int i = bus[p]; i != -1; i = e[i].nxt) {
            int q = e[i].p;
            if (e[i].c > 0 && dist[q] == dist[p] + e[i].w && vis[q] == 0) {
                int res = dinic_dfs(q, min(lim, e[i].c));
                cost += res * e[i].w;
                e[i].c -= res;
                e[i ^ 1].c += res;
                ret += res;
                lim -= res;
                if (lim == 0)
                    break;
            }
        }
        return ret;
    }
    void solve(int _s,int _t) {
        s=_s; t=_t;
        while (dinic_spfa()) {
            memset(vis, 0x00, sizeof vis);
            ans += dinic_dfs(s, inf);
        }
    }
    void init() {
        memset(bus, 0xff, sizeof bus);
    }
    }
    
    
    
    signed main() {
        int a,b;
        cin>>a>>b;
        flow::init();
        for(int i=a;i<=b;i++) {
            for(int j=a;j<=b;j++) {
                int x=i*i-j*j;
                if(i<=j) continue;
                int z=((int)sqrt(x));
                if(__gcd(z,j)!=1) continue;
                if(z*z!=x) continue;
                flow::make(i,j+b,1,-i-j);
                flow::make(j,i+b,1,-i-j);
            }
            flow::make(2*b+1,i,1,0);
            flow::make(i+b,2*b+2,1,0);
        }
        flow::solve(2*b+1,2*b+2);
        cout<<flow::ans/2<<" "<<-flow::cost/2;
    }
    
  • 相关阅读:
    python super()
    git用法小结(1)--建立远程仓库
    git用法小结(1)--建立远程仓库
    Linux下多线程查看工具(pstree、ps、pstack)
    JAVA操作Oracle数据库中的事务
    MyEclipse 2013优化配置【转】
    C语言多线程编程 死锁解析
    在linux终端执行clear或top命令时出现:'xterm' unknown terminal type的错误
    Linux中获取本机网络信息的几个函数及应用
    基于内存的通信之一 “内核共享消息队列”
  • 原文地址:https://www.cnblogs.com/mollnn/p/12883258.html
Copyright © 2011-2022 走看看