COGS731 [네트워크 흐름 24 문제] 최장 증자 서열(최대 흐름)
이 문제가 구한 것은 사실 가장 긴 비체감 서열이다.
첫 번째 질문은 고전적인 DP입니다. dp[i]는 서열 x1을 나타냅니다.xi 그리고 xi로 끝나는 LIS.
두 번째 질문은 용량 네트워크를 구축하는 것입니다.
그리고 그 최대 흐름이 답이다.
세 번째 질문, 두 번째 질문을 바탕으로 x1과 xn과 관련된 사이드 용량을 INF 달리기 최대 흐름으로 설정한다.또한 LIS가 1이면 n을 직접 출력하고 그렇지 않으면 INF가 됩니다.
1 #include<cstdio>
2 #include<cstring>
3 #include<queue>
4 #include<algorithm>
5 using namespace std;
6 #define INF (1<<30)
7 #define MAXN 1111
8 #define MAXM 2222222
9
10 struct Edge{
11 int v,cap,flow,next;
12 }edge[MAXM];
13 int vs,vt,NE,NV;
14 int head[MAXN];
15
16 void addEdge(int u,int v,int cap){
17 edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
18 edge[NE].next=head[u]; head[u]=NE++;
19 edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
20 edge[NE].next=head[v]; head[v]=NE++;
21 }
22
23 int level[MAXN];
24 int gap[MAXN];
25 void bfs(){
26 memset(level,-1,sizeof(level));
27 memset(gap,0,sizeof(gap));
28 level[vt]=0;
29 gap[level[vt]]++;
30 queue<int> que;
31 que.push(vt);
32 while(!que.empty()){
33 int u=que.front(); que.pop();
34 for(int i=head[u]; i!=-1; i=edge[i].next){
35 int v=edge[i].v;
36 if(level[v]!=-1) continue;
37 level[v]=level[u]+1;
38 gap[level[v]]++;
39 que.push(v);
40 }
41 }
42 }
43
44 int pre[MAXN];
45 int cur[MAXN];
46 int ISAP(){
47 bfs();
48 memset(pre,-1,sizeof(pre));
49 memcpy(cur,head,sizeof(head));
50 int u=pre[vs]=vs,flow=0,aug=INF;
51 gap[0]=NV;
52 while(level[vs]<NV){
53 bool flag=false;
54 for(int &i=cur[u]; i!=-1; i=edge[i].next){
55 int v=edge[i].v;
56 if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
57 flag=true;
58 pre[v]=u;
59 u=v;
60 //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
61 aug=min(aug,edge[i].cap-edge[i].flow);
62 if(v==vt){
63 flow+=aug;
64 for(u=pre[v]; v!=vs; v=u,u=pre[u]){
65 edge[cur[u]].flow+=aug;
66 edge[cur[u]^1].flow-=aug;
67 }
68 //aug=-1;
69 aug=INF;
70 }
71 break;
72 }
73 }
74 if(flag) continue;
75 int minlevel=NV;
76 for(int i=head[u]; i!=-1; i=edge[i].next){
77 int v=edge[i].v;
78 if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
79 minlevel=level[v];
80 cur[u]=i;
81 }
82 }
83 if(--gap[level[u]]==0) break;
84 level[u]=minlevel+1;
85 gap[level[u]]++;
86 u=pre[u];
87 }
88 return flow;
89 }
90
91 int d[555],a[555];
92 int main(){
93 freopen("alis.in","r",stdin);
94 freopen("alis.out","w",stdout);
95 int n;
96 scanf("%d",&n);
97 for(int i=1; i<=n; ++i) scanf("%d",a+i);
98 int lis=0;
99 for(int i=1; i<=n; ++i){
100 d[i]=1;
101 for(int j=1; j<i; ++j){
102 if(a[j]<=a[i]) d[i]=max(d[i],d[j]+1);
103 }
104 lis=max(lis,d[i]);
105 }
106 printf("%d
",lis);
107 if(lis==1){
108 printf("%d
%d",n,n);
109 return 0;
110 }
111 vs=0; vt=n<<1|1; NV=vt+1; NE=0;
112 memset(head,-1,sizeof(head));
113 for(int i=1; i<=n; ++i){
114 if(d[i]==1) addEdge(vs,i,1);
115 if(d[i]==lis) addEdge(i+n,vt,1);
116 addEdge(i,i+n,1);
117 }
118 for(int i=1; i<n; ++i){
119 for(int j=i+1; j<=n; ++j){
120 if(a[j]>=a[i] && d[j]==d[i]+1) addEdge(i+n,j,1);
121 }
122 }
123 printf("%d
",ISAP());
124 vs=0; vt=n<<1|1; NV=vt+1; NE=0;
125 memset(head,-1,sizeof(head));
126 for(int i=1; i<=n; ++i){
127 if(i==1 || i==n){
128 if(d[i]==1) addEdge(vs,i,INF);
129 if(d[i]==lis) addEdge(i+n,vt,INF);
130 addEdge(i,i+n,INF);
131 }else{
132 if(d[i]==1) addEdge(vs,i,1);
133 if(d[i]==lis) addEdge(i+n,vt,1);
134 addEdge(i,i+n,1);
135 }
136 }
137 for(int i=1; i<n; ++i){
138 for(int j=i+1; j<=n; ++j){
139 if(a[j]>=a[i] && d[j]==d[i]+1) addEdge(i+n,j,1);
140 }
141 }
142 printf("%d
",ISAP());
143 return 0;
144 }
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.