披著DP外衣的網路流
桂哥哥寫的沒有拆點的演算法居然AC了,結果我給他出了一個資料,結果就掛了,說明這題的資料給的太水了。。。
找到最長上升子序列,在所有的最長上升子序列中找到一種元素標號互不相同的情況,使序列個數做多
構圖方法:
將所有點拆點,保證其唯一性(在所有序列中只出現一次)
所有的DP為0,即可以做路徑起始點的和源點串連,DP為ans的點和匯點相連,邊權正無窮。
滿足dp[i]+1=dp[j]且a[i]<d[j]的兩點連一條正無窮的邊,這樣保證了每條可行流都是一條長度為ans+1的上升子序列,其他構圖方法有的能跑過資料,但是是錯的。
#include <cstdio>#include <cstring>#define max(a,b) (a>b?a:b)const int maxn=710;const int inf=5;const int s=0;struct edge{ int v,next,w;}edge[40005];int head[2*maxn],cnt;//for sapvoid addedge(int u, int v, int w){ edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].w=0; edge[cnt].next=head[v]; head[v]=cnt++;}int sap(int t){ int pre[2*maxn],cur[2*maxn],dis[2*maxn],gap[2*maxn]; int flow=0 , aug=inf ,u; bool flag; for (int i=0 ; i<=t ; ++i) { cur[i]=head[i]; gap[i]=dis[i]=0; } gap[s]=t+1; u=pre[s]=s; while (dis[s]<=t) { flag=0 ; for (int &j=cur[u] ; ~j ; j=edge[j].next) { int v=edge[j].v; if (edge[j].w>0 && dis[u]==dis[v]+1) { flag=1; if(edge[j].w<aug)aug=edge[j].w; pre[v]=u; u=v; if (u==t) { flow+=aug; while (u!=s) { u=pre[u]; edge[cur[u]].w-=aug; edge[cur[u]^1].w+=aug; } aug=inf; } break; } } if (flag)continue ; int mindis=t+1; for (int j=head[u]; ~j ; j=edge[j].next) { int v=edge[j].v; if (edge[j].w>0 && dis[v]<mindis) { mindis=dis[v]; cur[u]=j; } } if(--gap[dis[u]]==0)break; gap[dis[u]=mindis+1]++; u=pre[u]; } return flow;}void init (){ memset (head , -1 , sizeof(head)); cnt=0;}int n;int a[maxn];int dp[maxn];void build_graph(int len){ for (int i=0 ; i<n ; ++i) { addedge(i+1 , i+1+n , 1); if(dp[i]==0)//只有DP為0才能作為路徑起點,否則會出現更長的序列,與最長子序列矛盾 { addedge(0 , i+1 , inf); } if(dp[i]==len)//只有DP為len才能作為路徑終點 { addedge(i+1+n , 1404 , inf); } for (int j=i+1 ; j<n ; ++j) { if(a[i]<a[j]) { addedge(i+1+n , j+1 , inf); } } }}int main (){ while (~scanf("%d",&n)) { init(); for (int i=0 ; i<n ; ++i) { scanf("%d",a+i); } memset (dp , 0 , sizeof(dp)); for (int i=0 ; i<n ; ++i) { for (int j=0 ; j<i ; ++j) { if(a[i]>a[j]) dp[i]=max(dp[i],dp[j]+1); } } int ans=0; for (int i=0 ; i<n ; ++i) ans=max(ans,dp[i]); printf("%d\n",ans+1); build_graph(ans); printf("%d\n",sap(1404)); } return 0;}