給定一個有向圖,每條邊有兩種決策:「保留」(花費 a)或「刪除」(花費 b)。目標是以最小總花費,將圖改造為一張「隨機圖」。隨機圖需滿足:
s 與唯一出口 ts:出度 = 入度 + 1t:入度 = 出度 + 1本題是經典的「度數平衡」問題,可轉化為最小費用流模型:
ans。此時圖未必滿足度數條件。S、匯點 Ti,計算 temp[i] = out[i] - in[i](入口 s 再 -1,出口 t 再 +1)temp[i] > 0:S → i 容量 temp[i],費用 0(需流出)temp[i] < 0:i → T 容量 -temp[i],費用 0(需流入)u→v
a < b):加邊 u→v 容量 1,費用 b-a(改為刪除的額外代價)v→u 容量 1,費用 a-b(改為保留的額外代價)totflow,則答案為 ans + cost;否則輸出 impossible。bool spfa() {
fill(dis, dis+T+1, INF);
fill(vis, vis+T+1, 0);
fill(pre, pre+T+1, -1);
queue<int> q; q.push(S); dis[S]=0; vis[S]=1;
while(!q.empty()){
int u=q.front(); q.pop(); vis[u]=0;
for(int i=head[u]; ~i; i=ed[i].next){
if(!ed[i].w) continue;
int v=ed[i].v;
if(dis[v] > dis[u] + ed[i].c){
dis[v]=dis[u]+ed[i].c; pre[v]=i;
if(!vis[v]){ vis[v]=1; q.push(v); }
}
}
}
return dis[T]!=INF;
}
void mcmf(){
while(spfa()){
int tmp=INF;
for(int i=pre[T]; ~i; i=pre[ed[i].u]) tmp=min(tmp, ed[i].w);
for(int i=pre[T]; ~i; i=pre[ed[i].u]){
ed[i].w -= tmp; ed[i^1].w += tmp;
cost += tmp * ed[i].c;
}
flow += tmp;
}
}
N ≤ 100,邊數 M ≤ 2000s、出口 t 的度數修正:temp[s]--、temp[t]++ans、cost 可能較大)本題巧妙地將「最小化修改代價」轉化為「在滿足度數約束下的最小費用流」。關鍵洞見:先貪心鎖定基礎狀態,再用流網絡建模「翻轉決策」的代價與度數平衡需求。這是網絡流建模能力的優秀練習題。