kyeremal-网络流24题T4-魔术球问题

来源:互联网 发布:charge是什么软件 编辑:程序博客网 时间:2024/05/21 09:23

原题:04-魔术球问题


分析:直接求解较难,所以考虑使用二分/枚举答案+验证的方法,二分或枚举出一个答案后,即枚举出数字的集合:A=[1,N],那么对于每一组i,j∈A,如果i<j,且i+j为完全平方数,那么建立一条从i->j的有向边,那么问题就转化为求这个图的最小点路径覆盖。


code:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <algorithm>#include <queue>#include <vector> using namespace std; #define rep(i, l, r) for (int i = l; i <= r; i++)#define REP(i, l, r) for (int i = l; i >= r; i--)#define EPS (1e-7)#define INF 19971228#define MAXN 1000010 int n, N, first[MAXN], next[MAXN], S, T, dis[MAXN];struct tlist {int x, y, f;} a[MAXN];queue<int> q; inline int min(int a, int b) {return a<b ? a : b;}inline int max(int a, int b) {return a>b ? a : b;}inline double absD(double a, double b) {return (a > b) ? a-b : b-a;}inline bool square(int n) {return absD(sqrt(n*1.0), int(sqrt(n))) < EPS;} inline void add(int x, int y, int f) {    a[++N].x = x, a[N].y = y, a[N].f = f, next[N] = first[x], first[x] = N;    a[++N].x = y, a[N].y = x, a[N].f = 0, next[N] = first[y], first[y] = N;}inline void init() {    N = -1;    memset(next, -1, sizeof(next));    memset(first, -1, sizeof(first));} inline bool bfs() {    while (!q.empty()) q.pop();    memset(dis, -1, sizeof(dis));    q.push(S);    dis[S] = 0;    while (!q.empty()) {        int x = q.front();        q.pop();        for (int i = first[x]; ~i; i = next[i])            if (!~dis[a[i].y] && a[i].f) {                dis[a[i].y] = dis[x] + 1;                q.push(a[i].y);            }    }    return ~dis[T];} inline int find(int x, int low) {    int sum = 0, temp;    if (x == T) return low;    for (int i = first[x]; ~i; i = next[i])        if ((a[i].f) && (dis[a[i].y] == dis[x] + 1) && (temp = find(a[i].y, min(low-sum, a[i].f)))) {            a[i].f -= temp;            a[i^1].f += temp;            sum += temp;        }    return sum;} inline int dinic(int begin, int end) {    S = begin, T = end;    int temp, ans = 0;    while (bfs())        while (temp = find(S, 0x7fffffff))            ans += temp;    return ans;} inline int make(int K) {init();    rep(i, 1, K) add(0, i, 1);    rep(i, 1, K) add(K+i, 2*K + 1, 1);    rep(i, 1, K) rep(j, i+1, K)        if (square(i+j)) add(i, K+j, INF);    return K - dinic(0, 2*K + 1);} int main() {   // freopen("zyq.in", "r", stdin);    cin >> n;    int L = 1, R = 3000, mid;    while ((R-L) > 1) {        mid = (L + R) >> 1;        if (make(mid) <= n) L = mid;        else R = mid;    }    int out = 0;    if (make(R) <= n) out = R;    out = max(L, out);    cout << out << endl;    return 0;}


0 0
原创粉丝点击