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

2022-06-20 01:57:10 字數 1602 閱讀 8160

最長不下降子串行問題

分成三小問解決。

第一小問,求\(lis\),因為\(n<=500\),直接\(o(n^2)\)暴力求解即可。

第二三小問,建立模型用網路流求解。

對於第二小問

\((1)\)首先,因為每個點只能使用一次,考慮拆點,把每乙個點拆成\(i,n+i\)兩個點,從\(i\)連向\(n+i\)一條長度為\(1\)的有向邊。

\((2)\)其次,因為流向是從s經集合e到t,其中任意集合e中元素\(i\)需要滿足的條件是\(i\)位於lis上,故:

①出邊從\(lis[i]=k\)的點流向t

②所有的能構成e的邊都需要加入,也就是任意\(i,j\)滿足\(i都從\(i\)到\(j\)連邊。

跑一遍最大流即可。

第三小問唯一的不同就是\(s\)流向\(1\),\(1\)流向\(1+n\),\(n\)流向\(n+n\),\(n+n\)流向\(t\)四條路長度變成\(inf\)而已,改後再跑一遍最大流即可。

#include#includeint lis[1020],a[1020],len;//lis

int s,t,inf=0x3fffffff;//ek

struct edgeedge[50020];

int head[1020],cnt=2,vis[1020];

void addedge(int begin,int end,int length)

struct prepre[1020];

int bfs(),headq=0,tail=0,i;

queue[tail++]=s;

vis[s]=1;

while(headqedge[en].length)min=edge[en].length;

} for(i=t;i!=s;i=pre[i].pre)

ans+=min;

} return ans;

}int main()

//lis n<=500 o(n2)

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

for(j=1;j=a[j]&&lis[i]len)len=lis[i];

printf("%d\n",len);

//ek1 建圖求最大流

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

if(lis[i]==len)

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

} }printf("%d\n",ek());

//ek2

memset(pre,0,sizeof(pre));

memset(edge,0,sizeof(edge));

memset(head,0,sizeof(head));

cnt=2;

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

if(lis[i]==len)

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

} }addedge(1,1+n,inf); addedge(1+n,1,0);

addedge(s,1,inf); addedge(1,s,0);

if(lis[n]==len)

printf("%d\n",ek());

return 0;

}

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 提出的計算任務。輸入...

P2766 最長不下降子串行問題

通俗的,對於每個數只能取一次和取無限次,將點拆開加入邊約束 因為讓求最長上公升子串行的個數,所以當乙個數字被選擇時,它必須是最長上公升子串行的一部分 我們求出最長上公升子串行的 dp 陣列,當 x 可以連邊 y 當且僅當 y 在 dp 中可以從 x 轉移過來 這樣問題就顯然了,我們只需要求解 dag...