传送门
因为给出的是一个非A即B的问题,我们可以考虑一下最小割(不知道是不是在乱说。。)
然后我们可以定义对于一个点u,如果在切割后u与源点S相连,那么表示u在A集合,否则u与T相连,在B集合。
然后我们对于给出的无向图中已有的边(u,v),S连向u和v,流量为
∣
u
−
v
∣
|u-v|
∣u−v∣,表示如果u和v任意一个不在A集合,都将付出
∣
u
−
v
∣
|u-v|
∣u−v∣的代价。
然后我们对于给出的无向图中没有的边(u,v),u和v连向T,流量为
∣
u
−
v
∣
|u-v|
∣u−v∣,表示如果u和v任意一个不在B集合,都将付出
∣
u
−
v
∣
|u-v|
∣u−v∣的代价。
对于任意两个点u,v,给u和v连一条边,流量也是|u-v|,表示,如果u和v不在一个集合里面,将付出
∣
u
−
v
∣
|u-v|
∣u−v∣的代价。
考虑任意两个点u,v,都有一个与S或T构成的三角形,所以只要S和u和v任意一个和其他两个不在一个集合,那么就会付出
2
∣
u
−
v
∣
2|u-v|
2∣u−v∣的代价,就得不到题意中的分数
∣
u
−
v
∣
|u-v|
∣u−v∣。
所以答案就是
∑
u
,
v
∈
{
1
,
2
,
.
.
.
,
n
}
∣
u
−
v
∣
−
M
a
x
f
l
o
w
2
\frac{\sum_{u,v\in \{1,2,...,n\}}|u-v| -Maxflow}{2}
2∑u,v∈{1,2,...,n}∣u−v∣−Maxflow
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 5;
int n, m, S, T, a[MAXN], vd[MAXN], d[MAXN];
long long ans = 0;
inline void GET(int&n) {
char c; n = 0; do c = getchar(); while('0' > c || c > '9');
while('0' <= c && c <= '9') { n = n *10 + c - '0'; c = getchar(); }
}
bool mp[MAXN][MAXN];
int f[MAXN][MAXN];
inline int abs(int x) { return x > 0 ? x : -x; }
int Aug(int u, int augco) {
if(u == T) return augco;
int delta = 0, augc = augco, dmin = T-1;
for(int v = 1; v <= T; ++ v) if(f[u][v] > 0) {
if(d[v] + 1 == d[u]) {
delta = Aug(v, min(f[u][v], augc));
f[u][v] -= delta; f[v][u] += delta;
augc -= delta;
if(!augc || d[S] >= T) return augco - augc;
}
if(d[v] < dmin) dmin = d[v];
}
if(augco == augc) {
-- vd[d[u]];
if(!vd[d[u]]) d[S] = T;
++ vd[d[u] = dmin+1];
}
return augco - augc;
}
void sap() {
vd[0] = T;
while(d[S] < T)
ans += Aug(S, 0x3f3f3f3f);
}
int main() {
cin >> n >> m;
int u, v;
for(int i = 1; i <= m; ++ i) {
GET(u); GET(v);
mp[u][v] = mp[v][u] = 1;
}
S = n + 1; T = S + 1;
long long delta = 0;
for(int i = 1; i <= n; ++ i)
for(int j = i + 1; j <= n; ++ j) {
if(mp[i][j]) f[S][i] += j-i, f[S][j] += j-i;
else f[i][T] += j-i, f[j][T] += j-i;
f[i][j] += j-i; f[j][i] += j-i;
delta += j-i;
}
sap();
ans /= 2;
printf("%lld\n", delta - ans);
return 0;
}