这几类题目还是挺像的。
HDU 4183 其实也差不多。
类似的条件是每个点只能经过一次,然后要求权值递增。
经过一次这个条件可以用拆点来解决,而权值递增基本上用暴力都能解决了。。
这题就先做一个dp,
然后dp时把dp[j]+1 == dp[i] && a[j] < a[i] && j < i 的从j+n到i连一条容量为1的边。
最后再把dp[i] == 1 的和源点连边,把dp[j] == max 的和汇点连边。
最后最大流的结果就是上升子序列数。
然后我忘记加 a[j] < a[i]的条件WA一次,忘记拆点WA一次。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 1e5;
const int maxm = 2e6;
const int inf = 0x3f3f3f3f;
int n,m,a[maxn],dp[maxn],ans,tol;
int head[maxn],dis[maxn];
struct Edge
{
int to,cap,flow,nex;
Edge(int to,int cap,int flow,int nex): to(to),cap(cap),flow(flow),nex(nex) {}
Edge() {}
}edge[maxm];
void addedge(int u,int v,int cap,int rw=0)
{
edge[tol]=Edge(v,cap,0,head[u]); head[u]=tol++;
edge[tol]=Edge(u,rw,0,head[v]); head[v]=tol++;
}
void init()
{
memset(head,-1,sizeof head);
tol=ans=0;
}
bool bfs(int s,int t)
{
memset(dis,-1,sizeof dis);
dis[s]=0;
queue<int> que;
que.push(s);
while (!que.empty())
{
int u=que.front();que.pop();
for (int i=head[u];~i;i=edge[i].nex)
{
int v=edge[i].to;
if (dis[v]==-1 && edge[i].cap>edge[i].flow)
{
dis[v]=dis[u]+1;
if (v==t) return true;
que.push(v);
}
}
}
return false;
}
int dfs(int u,int t,int cap)
{
if (u==t) return cap;
int flow=0,f;
for (int i=head[u];~i;i=edge[i].nex)
{
int v=edge[i].to;
if (dis[v]==dis[u]+1 && edge[i].cap>edge[i].flow)
{
f=dfs(v,t,min(cap-flow,edge[i].cap-edge[i].flow));
edge[i].flow += f;
edge[i^1].flow -= f;
flow += f;
if (flow == cap) break;
}
}
if (!flow) dis[u]=-1;
return flow;
}
int dicnic(int s,int t)
{
int flow=0,a;
while (bfs(s,t))
while ((a=dfs(s,t,inf))>0)
flow += a;
return flow;
}
int main()
{
while (scanf("%d",&n)!=EOF)
{
init();
for (int i=1;i<=n;i++)
{
dp[i]=1;
scanf("%d",&a[i]);
for (int j=1;j<i;j++) if (a[j]<a[i]) dp[i] = max(dp[i],dp[j]+1);
ans=max(dp[i],ans);
for (int j=1;j<i;j++) if (dp[j]+1 == dp[i] && a[j]<a[i]) addedge(n+j,i,1);
addedge(i,i+n,1);
}
for (int i=1;i<=n;i++)
{
if (dp[i] == 1) addedge(0,i,1);
if (dp[i] == ans) addedge(n+i,2*n+1,1);
}
printf("%d\n",ans);
ans = dicnic(0,2*n+1);
printf("%d\n",ans);
}
return 0;
}