網路流 之 P2766 最長不下降子串行問題

2022-05-03 14:09:21 字數 2722 閱讀 9080

«問題描述:

給定正整數序列x1,...,xn 。

(1)計算其最長不下降子串行的長度s。

(2)計算從給定的序列中最多可取出多少個長度為s的不下降子串行。

(3)如果允許在取出的序列中多次使用x1和xn,則從給定序列中最多可取出多少個長度為s的不下降子串行。

«程式設計任務:

設計有效演算法完成(1)(2)(3)提出的計算任務。

輸入格式:

第1 行有1個正整數n,表示給定序列的長度。接下來的1 行有n個正整數n:x1, ..., xn。

輸出格式:

第1 行是最長不下降子串行的長度s。第2行是可取出的長度為s 的不下降子串行個數。第3行是允許在取出的序列中多次使用x1和xn時可取出的長度為s 的不下降子串行個數。

輸入樣例#1: 複製

4

3 6 2 5

輸出樣例#1: 複製

2

23

500n≤500

最長不下降子串行

這個題目第一問顯然是lis

第二問和第三問就轉化成最大流。

轉化過程(理解了好久)

第二問:

建圖,先求出f陣列,f[i]表示到第i為的最長的不下降子串行,

然後因為第二問每乙個數只能用一次,所以就把乙個點拆成乙個入點乙個出點。

建圖就是讓f[i]==1的和s連在一起,f[i]==ans的和t連在一起,然後中間如果有

a[i]>=a[j]&&i>j&&f[i]=f[j]+1 這樣的話就把 j 的出點和 i 的入點連在一起,這個就是建圖過程。

接下來說說為什麼這麼建圖,

首先只考慮第二問,因為每乙個點只能用一次,所以就把點拆開,並且權值為1 ,然後因為只有f[i]==1

才會和s點相連,設f[i]==1的個數為x,所以這個就說明最多只能有x個答案,在這個基礎上再看有沒有從這個

點出發可以到達f[i]==ans的。

接下來說說為什麼會 a[i]>=a[j]&&i>j&&f[i]=f[j]+1 這個j的出點和i的入點連在一起。

這個必須是這樣子寫的,因為只有這個樣子到f[i]==ans 的過程中把中間的數字標記一次,不讓別的再跑了。

例如說樣例: 3 6 2 5 這個ans=2 第二問答案有兩組就是 3 6 和 2 5,

3和2都與源點連起來了,6和5 都和匯點連起來了,3也會和6 5 連起來,2就只會和6 連起來,

然後這個答案可以是3 5 或者2 6 和2 5 ,很顯然後面的才是最大流。

然後第三問 首先你要看清楚題目,題目說的只是x1和xn可以用無數多次,

所以這個就只要改成 s 到1 和1到n+1 和 n到 n+n if(f[n]==ans) n到 t 這些邊改成無數次然後就再跑一次。

因為f[i]==1所以從s到1很有可能會跑很多次,所以,這個既然x1可以用無數多次,則要設s到1和1到1+n為無數多次

如果f[n]!=ans 則說明這個點不會和t連在一起,所以就不能連n到t,但是n到n+n可以連無數多次,不過好像沒什麼用。

因為n是最後乙個

#include #include 

#include

#include

#include

#include

#include

#include

#define inf 0x3f3f3f3f

using

namespace

std;

const

int maxn =1e5;

ints, t;

struct

node

};vector

e;vector

g[maxn];

void add(int u,int v,int

w)int

a[maxn], dp[maxn];

intlevel[maxn], iter[maxn];

void bfs(int

s) }

}}int dfs(int u,int v,int

f) }

}return0;

}int

dinic()

}int

main()

res =max(res, dp[i]);

}printf(

"%d\n

", res);

for (int i = 1; i <= n; i++) add(i, i + n, 1

);

for (int i = 1; i <= n; i++) if (dp[i] == 1) add(s, i, 1

);

for (int i = 1; i <= n; i++) if (dp[i] == res) add(i+n, t, 1

);

for(int i=1;i<=n;i++)

}int ans =dinic();

printf(

"%d\n

", ans);

add(s,

1, inf);

add(

1, 1 +n, inf);

if (dp[n] == res) add(n, t, inf),add(n, n +n, inf);

int ech =dinic();

printf(

"%d\n

", ech+ans);

return0;

}

P2766 最長不下降子串行問題 題解(網路流)

最長不下降子串行問題 分成三小問解決。第一小問,求 lis 因為 n 500 直接 o n 2 暴力求解即可。第二三小問,建立模型用網路流求解。對於第二小問 1 首先,因為每個點只能使用一次,考慮拆點,把每乙個點拆成 i,n i 兩個點,從 i 連向 n i 一條長度為 1 的有向邊。2 其次,因為...

P2766 最長不下降子串行問題

話不多說,直接上思路。其實這就是一道dp動態規劃的經典問題,首先鏈上題目描述 問題描述 設有整數序列b1,b2,b3,bm,若存在 i1 i2 i3 in,且 bi1 bi2 bi3 bin,則稱b1,b2,b3,bm中有長度為n的不下降序列bi1,bi2,bi3,bin。求序列中最大不下降子串行長...

P2766 最長不下降子串行問題

問題描述 給定正整數序列x1,xn 1 計算其最長不下降子串行的長度s。2 計算從給定的序列中最多可取出多少個長度為s的不下降子串行。3 如果允許在取出的序列中多次使用x1和xn,則從給定序列中最多可取出多少個長度為s的不下降子串行。程式設計任務 設計有效演算法完成 1 2 3 提出的計算任務。輸入...