一道費用流練習題

2021-10-02 03:54:27 字數 1539 閱讀 9351

在平面上有n條平行於y軸的線段,每條線段都有乙個權值,每次可以找出的y軸上投影互不重疊的若干線段,求m次後,找出的線段最大權值和為多少。(每條線段只能貢獻一次)

對於30%的資料,n<=100;m<=2;1<=y1考慮費用流,找m次可以當做總流量為m,然後首先的暴力方法是對於每條線段,與它互不重疊的線段連邊,這樣邊數是o(n

2)

o(n^2)

o(n2

)的,並不能過.

然後這裡好像算是乙個常見技巧:對數軸建邊,注意到由於是在y軸投影上互不重疊,所以x座標是沒有用的.所有的座標只有o

(5000

)o(5000)

o(5000

)級別,所以我們建出(i,i+1,inf,0)這種邊,形成縱座標軸,然後把原來的線段,流量為1,費用是權值,直接建在軸上,跑最大費用最大流.

考慮這樣的正確性,一條線段被選了以後,一條和它不相交的線段不會多增加流量,而一條和它相交的邊則會增加流量.所以正確.

#include

using

namespace std;

#define int long long

const

int maxn=

2e4+5;

const

int inf=

0x3f3f3f3f3f3f3f3fll

;inline

intread()

while

(isdigit

(c)&&

(c!=

eof)

)return t*f;

}int n,m,s;

struct edgee[maxn<<2]

;int h[maxn]

,cnt=1;

inline

void

add(

int a,

int b,

int c,

int d)

int cost,dis[maxn]

,vis[maxn]

,ht[maxn]

,t;bool

bfs()}

}}return dis[t]

!=st;

}int

dfs(

int u,

int rest)

vis[u]=1

;int tot=0;

for(

int&i=ht[u]

;i;i=e[i]

.p)}

return tot;

}void

dinic()

}}signed

main()

//printf("%d\n",s);

for(

int i=

1;i<

5e3+

5;i++

)//printf("%d\n",s);

dinic()

;printf

("%lld\n"

,cost)

;return0;

}

一道互動練習題

的做法 考慮逐位確定 對於每個位置,往後列舉有沒有位置可以使得正確位置更多,如果有,那麼有兩種情況,1是這個位置被放到了正確的位置,2是這個位置本來應該放的數被放來了 這裡的重點是我們需要區分1和2 具體的做法是記下讓這個位置答案正確位置數變大的2個位置,將其和i一起移位 這裡是手繪示意圖.即把p1...

一道fft練習題

考場上想到的o n 2 o n 2 o n2 暴力 記f i j f i j f i j 表示前i個位置,長度為j的連擊出現的期望次數 記g i j g i j g i j 表示第到i個位置為止,目前連擊次數為j的概率 轉移時有一些細節 include using namespace std con...

一道sam練習題

考慮答案實際上是每個子串的出現次數的平方和.這個可以通過手玩樣例驗證.考慮廣義sam 先將所有字串建成trie,然後再在trie上bfs,建出sam.考慮fail樹 每次插入乙個新節點,會改變從這個節點開始到根的路徑上的每個節點的right集合大小.所以考慮樹剖維護這種操作,然後每乙個單詞的答案就是...