給定正整數序列x1,..., xn。
(1)計算其最長遞增子串行的長度s。
(2)計算從給定的序列中最多可取出多少個長度為s的遞增子串行。
(3)如果允許在取出的序列中多次使用x1和xn,則從給定序列中最多可取出多少個長度為s的遞增子串行。
設計有效演算法完成(1)(2)(3)提出的計算任務
第1 行有1個正整數n(n<=500),表示給定序列的長度。
接下來的1 行有n個正整數x1,..., xn。
第1 行是最長遞增子串行的長度s。
第2行是可取出的長度為s 的遞增子串行個數。
第3行是允許在取出的序列中多次使用x1和xn時可取出的長度為s 的遞增子串行個數。
4 3 6 2 5
2 2
3
一開始自己想了個很鬼的模型30分,後來分析完全是錯的。
我那個模型並沒有求最大流,只是在殘餘網路上找路徑,所以不能保證答案是最大的。
先dp求出以每個點的為起點的最長不下降序列長度,以為f[i];
注意是最長不下降,這題題面與資料不符合(坑了我1個小時)
將乙個點一分為二,分為a部和b部。
ai和bi連一條容量為1的邊。
若f[i]==max
s->ai,
若f[i]==1
bi->
t。
列舉i後面的j,若a[i]<=a[j]
且f[j]+1==f[i],
連bi->aj
。
然後跑最大流。
第三問是一樣的,只是把s和t連1和n還有a1連b1的邊,an連
bn的邊容量改為inf。
1 #include2 #include3 #include4 #include5 #include6 #include7 #include
8 #include9 #include10 #include11 #include12 #include13 #include14
using
namespace
std;
15struct
datae[530000],g[530000
];18
int head[1010],edge=-1,a[510],lev[1010],f[510
],n;
19void add(int
from,int to,int
w)25
bool bfs(int s,int
t)38}39
return0;
40}41int dfs(int s,int t,int
k)52
return
tag;53}
54void dinic(int s,int
t)59
int zd=0;60
void
dp()
70int
main()
7182
for(int i=1;i<=n;i++) add(i,i+n,1),add(i+n,i,0
);83
for(int i=1;i<=n;i++)
85if(f[i]==1) 86}
87for(int i=1;i<=n;i++)
88for(int j=i+1;j<=n;j++)
89if(a[j]>=a[i] && f[j]+1==f[i]) add(i+n,j,1),add(j,i+n,0
);90 memcpy(e,g,sizeof
(e));
91dinic(s,t);
92if(f1) add(s,1,1999999999),add(1,s,0
);93
if(f2) add(2*n,t,1999999999),add(t,2*n,0
);94 add(1,n+1,1999999999),add(n+1,1,0
);95 add(n,2*n,1999999999),add(2*n,n,0
);96 memcpy(e,g,sizeof
(e));
97dinic(s,t);
98return0;
99 }
網路流 24 題 最長遞增子串行
1 dp求一遍 2 所有點拆成入點和出點,對於沒個f i 1的1點連源點,每個f i ans1的點連匯點,每個點的入點和出點再連一條邊,所有容量為1,求一遍最大流。2 1和n可以用多次,所以對於點1和點n,入點和出的連邊的容量變為inf,如果需要連源點或匯點那麼容量也變為n,其餘容量為1,求一遍最大...
網路流24題 最長遞增子串行
輸入檔案 alis.in輸出檔案 alis.out簡單對比 時間限制 1 s 記憶體限制 128 mb 問題描述 給定正整數序列x1,xn。1 計算其最長遞增子串行的長度s。2 計算從給定的序列中最多可取出多少個長度為s的遞增子串行。3 如果允許在取出的序列中多次使用x1和xn,則從給定序列中最多可...
網路流24題6 最長遞增子串行
給定正整數序列x1,xn 1 計算其最長遞增子串行的長度s。2 計算從給定的序列中最多可取出多少個長度為s的遞增子串行。3 如果允許在取出的序列中多次使用x1和xn,則從給定序列中最多可取出多少個長度為s的遞增子串行。設計有效演算法完成 1 2 3 提出的計算任務。第一問秒掉 第二問比較難想到,每個...