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;
}