hkr04 @ 2020-03-28 13:50:04
不拆点已A,有可能是数据过弱。
图示例子是一种卡掉的情况,但是我好像不知道怎么构造出这样的数据。
代码:
#include <cstdio>
#include <cstring>
const int maxn=500+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int a[maxn],f[maxn],dep[maxn];
int cur[maxn],head[maxn],to[maxm],nxt[maxm],val[maxm];
int tot=1,cnt=0;
int n,s,t;
struct Queue
{
int a[maxn<<1];
int l,r;
Queue() {l=1,r=0;}
void push(int x) {a[++r]=x;}
void pop() {l++;}
int front() {return a[l];}
bool empty() {return l>r;}
}q;
int min(int x,int y) {return x<y?x:y;}
int max(int x,int y) {return x>y?x:y;}
void add(int u,int v,int w)
{
nxt[++tot]=head[u];
head[u]=tot;
to[tot]=v;
val[tot]=w;
}
bool bfs()
{
memset(dep, 0x3f, sizeof(dep));
dep[s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
for (int i=head[u];i;i=nxt[i])
{
int v=to[i];
if (val[i]&&dep[v]>dep[u]+1)
{
dep[v]=dep[u]+1;
q.push(v);
}
}
}
return dep[t]!=INF;
}
int dfs(int u,int minf)
{
if (u==t||!minf)
return minf;
int used=0;
for (int &i=cur[u];i;i=nxt[i])
{
int v=to[i];
if (val[i]&&dep[v]==dep[u]+1)
{
int flow=dfs(v, min(minf-used, val[i]));
if (!flow)
continue;
used+=flow;
val[i]-=flow;
val[i^1]+=flow;
if (used==minf)
break;
}
}
return used;
}
int main()
{
scanf("%d",&n);
s=0,t=n+1;
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;i<=n;i++)
f[i]=1;
int sum=1;
for (int i=1;i<=n;i++)
for (int j=i-1;j>=1;j--)
if (a[j]<=a[i])
f[i]=max(f[i], f[j]+1);
for (int i=1;i<=n;i++)
sum=max(sum, f[i]);
if (sum==1)
{
printf("%d\n%d\n%d\n",sum,n,n);
return 0;
}
printf("%d\n",sum);
for (int i=1;i<=n;i++)
{
if (f[i]==1)
add(s, i, 1),add(i, s, 0);
if (f[i]==sum)
add(i, t, 1),add(t, i, 0);
for (int j=i+1;j<=n;j++)
if (a[i]<=a[j]&&f[i]+1==f[j])
add(i, j, 1),add(j, i, 0);
}
int ans=0;
while(bfs())
{
for (int i=s;i<=t;i++)
cur[i]=head[i];
ans+=dfs(s, INF);
}
printf("%d\n",ans);
ans=0;
for (int i=2;i<=tot;i++)
{
if (i&1)
val[i]=0;
else
val[i]=(to[i]==1&&to[i^1]==s)||(to[i]==t&&to[i^1]==n)?INF:1;
}
while(bfs())
{
for (int i=s;i<=t;i++)
cur[i]=head[i];
ans+=dfs(s, INF);
}
printf("%d\n",ans);
return 0;
}
by HearTheWindSing @ 2020-03-28 13:50:18
%%%
by 随情英 @ 2020-03-28 13:54:04
一个中间点,有多条出边和入边,就行了
by hkr04 @ 2020-03-28 13:56:05
我知道拆点可以限制点的使用次数,只是很好奇到底能不能卡掉这样的做法。
显然拆点可以避免掉最终3用两次的情况。
by hkr04 @ 2020-03-28 13:56:55
@随情英 我明白并已举出例子,现在我想要这样的数据
by Smile_Cindy @ 2020-03-28 14:14:10
@hkr04 数据来了
5
2 1 3 5 4
by hkr04 @ 2020-03-28 14:31:49
@Alpha 感谢!
by hkr04 @ 2020-03-28 14:32:53
@Alpha 但是第一问就错了呀
by hkr04 @ 2020-03-28 14:35:50
@Alpha 题解区跑出来的是
3
1
1
错误答案:
3
2
2
by Smile_Cindy @ 2020-03-28 15:28:02
@hkr04 手残,我的stdout是手写的。
by Smile_Cindy @ 2020-03-28 15:29:03
真正的stdout:
3
1
1