最小費用最大流POJ 3680

2021-09-16 20:31:45 字數 2731 閱讀 8836

類似問題,比如有k的限制,某件事情只能做k次,或者事件一一對應,都可以建圖跑流來解決。比線段樹好使我感覺。

從s-1-2-3-。。。-t建立一條通路(先離散化了頂點的,離散模板就好了),代價為零,流量為k(其實是多少無所謂,比k就行)。

然後如果1-3有區間的話,就建立一條負的代價,因為求的是最大費用,模板我們都是用的最小費用,流量為1。

這裡為什麼要這麼建圖,因為每乙個區間,被覆蓋不超過k次,求最大流我們能想到時盡量然他去覆蓋,得到代價,為此s出來的流量為k,又因為整個圖從左到右的流動,所以每個頂點,最多走k次,就可以保證,每乙個點在我們選的區間內,最多被k個區間給覆蓋掉了。這也就是為什麼從s-t的邊,流量只要大於k就行了,因為整個流量只有k,不會超過的。

然後對於負權值,可以先算勢函式,h,不過由於初始化是負的,直接dijstra不行,bellman演算法才能跑。

第二種就是直接拉滿,然後跑bellman演算法,乘以代價,最後取負號就行了。

(spfa演算法感覺還是危險,有些題目是會卡spfa的,所以還是老實用bellman好了)

畢竟網路流圖重點不是求路徑。ev的時間複雜度還是能接受的。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

//#include

#include

#define up(i,a,b) for(int i=a;i#define dw(i,a,b) for(int i=a;i>b;i--)

#define upd(i,a,b) for(int i=a;i<=b;i++)

#define dwd(i,a,b) for(int i=a;i>=b;i--)

//#define local

typedef

long

long ll;

const

double esp =

1e-6

;const

double pi =

acos(-

1.0)

;const

int inf =

1e9;

using

namespace std;

typedef pair<

int,

int> pir;

int t;

int n, k;

struct edge

;vector g[

100003];

//鄰接矩陣

int a[

100005];

int b[

100005];

int w[

100005];

int dist[

100005];

int preve[

100005];

int prevv[

100005];

void

addedge

(int from,

int to,

int cost,

int cap));

//他的反邊是新增的to的邊

g[to]

.push_back

(edge);

//他的反邊是from-1

}int

bell_man

(int s,

int t,

int f)

//bellman}}

}if(dist[t]

== inf)

//f沒有跑完,但是已經鬆弛到了最多,明顯跑不過去了

int d = f;

for(

int i = t; i != s; i = prevv[i]

)//求最小流

f -= d;

res +

= d * dist[t]

;//最大費用

for(

int i = t; i != s; i = prevv[i])}

return res;

}int

main()

sort

(x.begin()

,x.end()

);x.

erase

(unique

(x.begin()

, x.

end())

,x.end()

);//離散化

int lenth = x.

size()

;up(i,0

, lenth+2)

//g一定要清零的

up(i,

0, n)

addedge(0

,1,0

, k)

;//s頂點連邊

addedge

(lenth, lenth +1,

0, k)

;//終點連邊

up(i,

0, lenth-1)

//從左到右,費用為零的通路邊

int res=

-bell_man(0

, lenth +

1, k)

;//負的最大費用

cout << res << endl;

}return0;

}

poj 3680 最小費用最大流

思路 因為n 200,而區間範圍為 1,100000 因此需要離散化,去重,然後就是建圖了相連兩點連邊,容量為k,費用為0,然後就是對區間端點進行連邊,容量為1,費用為權值,最後就是跑費用流了。1 include2 include3 include4 include5 include6 using ...

POJ 3680 最小費用最大流

include include include include include include using namespace std const int maxn 500 const int maxm 1e5 10 const int inf 0x3f3f3f3f struct edge edge...

poj 3680 最小費用最大流

思路 因為n 200,而區間範圍為 1,100000 因此需要離散化,去重,然後就是建圖了相連兩點連邊,容量為k,費用為0,然後就是對區間端點進行連邊,容量為1,費用為權值,最後就是跑費用流了。1 include2 include3 include4 include5 include6 using ...