王子 費用流

2022-03-07 06:09:20 字數 1558 閱讀 4739

給定$n,k,p,q$,現在要給一段長度為n的格仔染黑白,第$i$個格仔染成黑色得到$a_i$分,白色$b_i$分

要求連續的$k$個格仔中要有至少$p$個黑的,$q$和白的

求最大得分

一眼是沒想法的......瞄了一眼題解看到「網路流」三個大字,就會了

還是要多想一些方法,多試試,因為這種題看著不是dp就是什麼鬼畜的轉化,那轉化模型肯定先看是不是網路流

考慮序列模型的經典網路流轉化方法

本題中的核心限制是對於每一段$k$區間的顏色數限制

可以看到實際上這個$p,q$就是限制黑色格仔的數量是$[p,k-q]$

同時這個限制對於每乙個格仔而言,這個格仔參與$k$個區間的限制

我們考慮這樣乙個方法:

首先把所有的都塗成白色,然後用跨越乙個$k$區間的一點流量來代表變成乙個黑格仔帶來的影響,其他的從$i$到$i+1$的代表乙個白格仔

那麼這樣我們把白格仔邊設成流量上限為$k-q-p$上限,費用為0,代表額外的白變黑的數量上限

黑格仔邊顯然容量為1,費用為對應的格仔的$b_i-a_i$

一些細節注意:

首先這個跨越的黑格仔邊,從$i$出發,終點在$k+i$不是在$k+i-1$

然後注意最開始的$k$個點,沒有前驅去到達它們,那麼建立乙個輔助節點$aux$,從$s->aux$連一條容量為$k-q$的(限制一下),再從$aux$連向$1$到$k$號點

實現上可以把費用流的$ans$初值設為所有白格仔分數的和,然後用上面定義的費用直接算就可以了

費用流推薦使用spfa魔改版zkw多路增廣,不過本題中單路多路其實差距不大,$ek$還可能更快(因為圖的形態問題)

#include#include#include#include#include#include#define ll long long

using namespace std;

inline ll read()

while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();

return re*flag;

}ll n,m,l,r,cnte=1,first[1010],dis[1010],vis[1010],ans=0,maxf=0;

struct edgea[20010];

inline void add(ll u,ll v,ll w,ll cap);first[u]=cnte;

a[++cnte]=(edge);first[v]=cnte;

}queueq;

bool spfa(ll s,ll t)

} }return dis[s]!=-111111111111111ll;

}ll dfs(ll u,ll t,ll lim)

} }dis[u]=-111111111111111ll;

return flow;

}void mcmf(ll s,ll t) }}

ll x[1010],y[1010];

int main()

mcmf(0,n+1);

cout<}

網路流 費用流

這個好像不考 沒事可以騙分 費用流,顧名思義,就是有費用的流,也就是說,給乙個網路流圖中的每條弧增加乙個單位流量費用。一般來說求解的費用流都是最大流最小費用。好像沒什麼好bb的 這裡推薦使用zkw演算法求解最小費用流,看著 理解就行,應該還是很好理解的。zkw演算法在稠密圖上跑得飛快,在稀疏圖上還不...

網路流 費用流

網路流有很多種類 其中最大流 有增廣路演算法和預流推進演算法。增廣路演算法就是不斷的新增增廣路。其中的dinic演算法。會稍微提到isap演算法 poj1273 首先想到dfs一直往後延伸,然後從源點到匯點計算每條路,但是這樣只是單條路的最值,有時可能因為走一條路而間接的認定了除這條路以外的某個路通...

費用流模板

const int oo 1e9 無窮 const int mm 11111111 邊 const int mn 888888 點 int node,src,dest,edge int ver mm flow mm cost mm nex mm int head mn dis mn p mn q m...