5972. 【北大2019冬令营模拟12.1】 wang(2s,256MB)
Problem
-
给定一个定义域和值域都在 Z Z Z上的函数 F ( x ) F(x) F(x),且给定一个常数 C C C,且满足 F ( 2 F ( x ) − x + 1 ) = F ( x ) + C F(2F(x) - x + 1) = F(x) + C F(2F(x)−x+1)=F(x)+C
-
现在给定你 n n n个二元组 ( x i , y i ) (x_i,y_i) (xi,yi),要求最小化 ∑ i = 1 n ∣ F ( x i ) − y i ∣ \sum_{i=1}^n|F(x_i)-y_i| i=1∑n∣F(xi)−yi∣
Data constraint
-
C ≤ 60 C\le 60 C≤60
-
n ≤ 10000 n\le 10000 n≤10000
Solution
-
性质①
F ( x + 2 C ) = F ( x ) + 2 C F(x+2C)=F(x)+2C F(x+2C)=F(x)+2C
证明①
令 y = 2 F ( x ) − x + 1 y=2F(x)-x+1 y=2F(x)−x+1
则
F ( y ) = F ( x ) + C F(y)=F(x)+C F(y)=F(x)+C ⇓ \Downarrow ⇓ F ( y ) + C = F ( x ) + 2 C F(y)+C=F(x)+2C F(y)+C=F(x)+2C ⇓ \Downarrow ⇓ F ( 2 F ( y ) − y + 1 ) = F ( x ) + 2 C F(2F(y)-y+1)=F(x)+2C F(2F(y)−y+1)=F(x)+2C 2 F ( y ) − y + 1 = 2 F ( y ) − 2 F ( x ) + x = x + 2 C 2F(y)-y+1=2F(y)-2F(x)+x=x+2C 2F(y)−y+1=2F(y)−2F(x)+x=x+2C ⇓ \Downarrow ⇓ F ( x + 2 C ) = F ( x ) + 2 C F(x+2C)=F(x)+2C F(x+2C)=F(x)+2C
-
性质②:
-
若 a + b = 2 t + 1 , F ( a ) = t a+b=2t+1,F(a)=t a+b=2t+1,F(a)=t
-
则 F ( a ) + F ( b ) = 2 t + C F(a)+F(b)=2t+C F(a)+F(b)=2t+C
-
证明②
- 令 a = 2 a ′ , b = 2 b ′ + 1 , t = a ′ + b ′ a=2a',b=2b'+1,t=a'+b' a=2a′,b=2b′+1,t=a′+b′
- 则 F ( 2 F ( a ) − a + 1 ) = F ( a ) + C F(2F(a)-a+1)=F(a)+C F(2F(a)−a+1)=F(a)+C ⇓ \Downarrow ⇓ F ( 2 ( t + n C ) − a + 1 ) = t + n C + C F(2(t+nC)-a+1)=t+nC+C F(2(t+nC)−a+1)=t+nC+C ⇓ \Downarrow ⇓ F ( 2 t − a + 1 + 2 n C ) = t + n C + C F(2t-a+1+2nC)=t+nC+C F(2t−a+1+2nC)=t+nC+C ⇓ \Downarrow ⇓ F ( 2 t − a + 1 ) + 2 n C = t + n C + C F(2t-a+1)+2nC=t+nC+C F(2t−a+1)+2nC=t+nC+C ⇓ \Downarrow ⇓ F ( b ) = t − ( n − 1 ) C F(b)=t-(n-1)C F(b)=t−(n−1)C
-
然后根据这两个性质,把所有的 X i X_i Xi按照 2 C 2C 2C取模之后可以分成 2 C 2C 2C组,每一组当中只要一个对应的值确立,整个组的值便可以确立.
-
所以我们只需考虑组与组之间的对应关系。
-
并且根据题意,当 F ( a ) F(a) F(a)等于某个值 t t t时,只有 F ( 2 t − a + 1 ) F(2t-a+1) F(2t−a+1)与 F ( a ) F(a) F(a)有关系,所以,很明显只有奇偶性不同的组互相影响.
-
根据性质②,我们得知当 F ( a ) = t + n C F(a)=t+nC F(a)=t+nC时,对应的 F ( 2 t − a + 1 ) = t − ( n − 1 ) C F(2t-a+1)=t-(n-1)C F(2t−a+1)=t−(n−1)C,换言之,对于所有的 X i X_i Xi,若其属于某组 a a a(即 X i ≡ a ( m o d 2 C ) X_i\equiv a(mod\ 2C) Xi≡a(mod 2C)),那么可以考虑与其奇偶性不同的所有组 b b b,组 a a a与不同的组 b b b进行影响会产生不同的代价,而我们需要做的,是让所有的奇数组与偶数组进行完美配对.
-
要明白这一点,首先要知道什么叫完美配对.
-
给定一个二分图,如果可以分成两个相等集合 S , T S,T S,T,并且 S S S中每个点与且仅与 T T T中一个点进行匹配,那么这个二分图就可以完美配对.
-
对于此题而言,因为每个 F ( a ) F(a) F(a) 影响且仅能影响一个对应的 F ( b ) F(b) F(b),并且影响了 F ( b ) F(b) F(b)之后,既不能影响另一个 F ( c ) F(c) F(c),又不能被另一个 F ( c ) F(c) F(c)影响,所以这显然是一个二分图,显然是可以进行完美配对的。
-
为了更好地计算出两组 a , b a,b a,b相互影响的代价,观察到实际上 F ( a ) F(a) F(a)只能变成 t + n C t+nC t+nC的形式,而 F ( b ) F(b) F(b)也是类似于这个形式,所以我们要计算 ∑ i = 1 n ∣ F ( X i ) − Y i ∣ \sum_{i=1}^n|F(X_i)-Y_i| ∑i=1n∣F(Xi)−Yi∣的代价,就可以想办法把式子转化成类似于 ∑ i = 1 n ∣ W i + n ∗ C ∣ \sum_{i=1}^n|W_i+n*C| ∑i=1n∣Wi+n∗C∣的形式,事实证明,这很容易做到.
-
考虑两组 a , b a,b a,b,不妨假设 a = 2 a ′ , b = 2 b ′ + 1 a=2a',b=2b'+1 a=2a′,b=2b′+1,那么如果一个 X i X_i Xi在对应的 a a a组,我们就令 W i = F ( X i ) − Y i = F ( a ) + X i − a − Y i = a ′ + b ′ + X i − a − Y i W_i=F(X_i)-Y_i=F(a)+X_i-a-Y_i=a'+b'+X_i-a-Y_i Wi=F(Xi)−Yi=F(a)+Xi−a−Yi=a′+b′+Xi−a−Yi,
-
即 W i = a ′ + b ′ + X i − a − Y i W_i=a'+b'+X_i-a-Y_i Wi=a′+b′+Xi−a−Yi.
-
反之,如果 X i X_i Xi在 b b b组,我们就令 W i = F ( X i ) − Y i = F ( b ) + X i − b − Y i = a ′ + b ′ + C + X i − b − Y i W_i=F(X_i)-Y_i=F(b)+X_i-b-Y_i=a'+b'+C+X_i-b-Y_i Wi=F(Xi)−Yi=F(b)+Xi−b−Yi=a′+b′+C+Xi−b−Yi,因为 W i W_i Wi在式子里是套上了绝对值的,所以我们可以把它变成 W i = Y i + b − a ′ − b ′ − X i − C W_i=Y_i+b-a'-b'-X_i-C Wi=Yi+b−a′−b′−Xi−C,
-
即 W i = Y i + b − a ′ − b ′ − X i − C W_i=Y_i+b-a'-b'-X_i-C Wi=Yi+b−a′−b′−Xi−C
-
这样一来,所有的 ∣ F ( X i ) − Y i ∣ |F(X_i)-Y_i| ∣F(Xi)−Yi∣都可以变化成 ∑ i = 1 n ∣ W i + n ∗ C ∣ \sum_{i=1}^n|W_i+n*C| i=1∑n∣Wi+n∗C∣.
-
我们取中位数,并适当调整,可以很容易确定一个最优的 n n n.
-
这样子便可以计算出两组 a , b a,b a,b进行配对的最优代价,接下来就是如何最小权匹配了.
-
对于这个算法,我们可以直接转化最小费用最大流.
-
最小费用最大流需要注意它是在保证最大流的前提下最小费用的,所以我们可以按照正常思维,从原点向左边一排点连容量为 1 1 1,费用为 0 0 0的边,汇点同样向右边一排点这样连边,之后,对于中间的连边,流量为 1 1 1,费用就是匹配代价,之后用 Z K W ZKW ZKW算法跑一遍就可以得到答案了.
-
因为本人太菜,所以这里大致讲一讲费用流的实现.
-
求解费用流一般有两种算法:第一种就是刚刚提到的大名鼎鼎的 Z K W ZKW ZKW算法,也是实战中经常用到的算法,另外一种就是经典的 s p f a spfa spfa增广算法.
SPFA增广
- 一句话,每次找一条费用最小的流进行增广,直到不能增广为止.
#define I register int
void link(I x, I y, I z, I l) {
tov[++ tot] = y, len[tot] = z, nex[tot] = las[x], cost[tot] = l, las[x] = tot;
tov[++ tot] = x, len[tot] = 0, nex[tot] = las[y], cost[tot] = -l, las[y] = tot;
}
bool spfa() {
queue<int> q;
mem(d, 0xcf), mem(v, 0), q.push(S), d[S] = 0, v[S] = 1, incf[S] = 1 << 30;
while (q.size()) {
I x = q.front(); v[x] = 0; q.pop();
for (I i = las[x], y = tov[i]; i; i = nex[i], y = tov[i])
if (len[i] && d[y] < d[x] + cost[i]) {
d[y] = d[x] + cost[i], incf[y] = min(incf[x], len[i]), pre[y] = i;
if (!v[y]) v[y] = 1, q.push(y);
}
}
return d[T] > 0;
}
void update() {
for (I x = T; x ^ S;)
len[pre[x]] -= incf[T], len[pre[x] ^ 1] += incf[T], x = tov[pre[x] ^ 1];
maxflow += incf[T], ans += d[T] * incf[T];
}
while (spfa()) update();
ZKW算法
#define ll long long
void link(ll x, ll y, ll l, ll L) {
tv[++ tt] = y, c[tt] = L, nx[tt] = ls[x], ls[x] = tt, len[tt] = l;
tv[++ tt] = x, c[tt] = 0, nx[tt] = ls[y], ls[y] = tt, len[tt] = -l;
} //c[x]表示x这条边的流量,len[x]表示x这条边的费用
bool bfs() { //这里与spfa增广几乎是一模一样的,核心都是找出从原点到所有点的最小费用.
mem(vis, 0), mem(dis, 0x7f), dis[S] = 0, vis[S] = 1;
queue <ll> Q; Q.push(S);
while (!Q.empty()) {
ll k = Q.front(); Q.pop();
for (ll x = ls[k]; x ; x = nx[x])
if (c[x] && dis[tv[x]] > dis[k] + len[x]) {
dis[tv[x]] = dis[k] + len[x]; //更新最小费用
if (!vis[tv[x]])
vis[tv[x]] = 1, Q.push(tv[x]);
}
vis[k] = 0;
}
return dis[T] < 9187201950435737471;
}
ll dfs(ll k, ll flow) {
if (k == T) { vis[T] = 1; return flow; }
ll have = 0; vis[k] = 1;
//这里一定要注意这个vis标记的作用,因为dis[i]表示的是最小费用,而并非普通dinic的距离标号
//所以这是可能存在零环的,因此一定要用个标记来去掉零环带来的影响.
for (ll x = ls[k]; x ; x = nx[x])
if (!vis[tv[x]] && c[x] && dis[tv[x]] == dis[k] + len[x]) {
ll now = dfs(tv[x], min(flow - have, c[x]));
ans += now * len[x], c[x] -= now, c[x ^ 1] += now, have += now;
if (flow == have) return have;
}
return have;
}
int main() {
while (bfs())
for (vis[T] = 1; vis[T]; )
mem(vis, 0), dfs(S, inf);
}
-
实际上 Z K W ZKW ZKW的算法就是借鉴了普通的最大流 d i n i c dinic dinic算法以及原始 s p f a spfa spfa算法。
-
在求出了 d i s [ i ] dis[i] dis[i],即最小花费之后每次多路增广,而不仅仅只是增广一条最优的路径(这是 s p f a spfa spfa增广),这样可以少进行很多次 s p f a spfa spfa,提高效率.
-
所以综上,也不难发现,在稠密图上 Z K W ZKW ZKW一般是占据优势的,但在极稀疏的图上, s p f a spfa spfa增广一般更优.