給定$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...