【题解】数字梯形问题
【题解】数字梯形问题
这样一道傻题我调了这么久
三个任务建图是这样的,由于太简单就不xjb解释了,一个点拆位入点和出点
graph LR
S==w=1,c=1==>入点1
入点1 --w=1,c=点权1--> 出点1
入点2 --w=1,c=点权2--> 出点2
入点3 --w=1,c=点权2--> 出点3
出点1 --w=1,c=0--> 入点2
出点1 --w=1,c=0--> 入点3
出点2 ==w=1==>T
出点3 ==w=1==>T
graph LR
S==w=1,c=1==>入点1
入点1 --w=2,c=点权1--> 出点1
入点2 --w=2,c=点权2--> 出点2
入点3 --w=2,c=点权2--> 出点3
出点1 --w=1,c=0--> 入点2
出点1 --w=1,c=0--> 入点3
出点2 ==w=inf==>T
出点3 ==w=inf==>T
graph LR
S==w=1,c=1==>入点1
入点1 --w=inf,c=点权1--> 出点1
入点2 --w=inf,c=点权2--> 出点2
入点3 --w=inf,c=点权2--> 出点3
出点1 --w=inf,c=0--> 入点2
出点1 --w=inf,c=0--> 入点3
出点2 ==w=inf==>T
出点3 ==w=inf==>T
一次加边即可,不过由于是费用流所以貌似要重置残余网络
注意数组大小和边界!好坑。
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=1e3+5;
struct E{
int to,nx,w,c;
E(){to=nx=c=w=0;}
E(const int&a,const int&b,const int&C,const int&d){to=a;nx=b;w=C;c=d;}
inline void print(){
printf("to=%d nx=%d w=%d c=%d\n",to,nx,w,c);
}
}e[maxn*maxn<<3];
int head[maxn*15];
int cnt=1;
int data[55][55];
int id[55][55];
int nodecnt;
int S,T;
int n,m;
int ts,tt;
inline void add(const int&fr,const int&to,const int&w,const int&c,const int&f=1){
//if(cnt>=(maxn*maxn<<3)) puts("WA"),exit(1);
// printf("%d %d %d %d %d\n",fr,to,w,c,f);
e[++cnt]=E(to,head[fr],w,c);
head[fr]=cnt;
if(f)add(to,fr,0,-c,0);
}
queue < int > q;
const int inf=0x3f3f3f3f;
int in[maxn*15];
int fl[maxn*15];
int last[maxn*15];
int d[maxn*15];
inline int mincost(){
int ret=0;
while(1){
for(register int t=1;t<=nodecnt;++t) d[t]=inf,fl[t]=0,in[t]=0;
d[S]=0;q.push(S);fl[S]=inf;
while(q.size()){
register int now=q.front();
q.pop();
in[now]=0;
//cout<<"now="<<now<<' '<<T<<endl;
for(register int t=head[now];t;t=e[t].nx){
if(d[e[t].to]>d[now]+e[t].c&&e[t].w>0){
d[e[t].to]=d[now]+e[t].c;
fl[e[t].to]=min(e[t].w,fl[now]);
last[e[t].to]=t;
if(!in[e[t].to]) q.push(e[t].to);
in[e[t].to]=1;
}
}
}
//cout<<"fl[T]="<<fl[T]<<endl;
if(fl[T]==0)break;
ret+=d[T]*fl[T];
for(register int t=T;t!=S;t=e[last[t]^1].to)
e[last[t]].w-=fl[T],e[last[t]^1].w+=fl[T];
}
return ret;
}
inline void reset(){
for(register int t=2;t<=cnt;t+=2){
e[t].w+=e[t+1].w;
e[t+1].w=0;
//e[t].print();
//e[t+1].print();
}
}
int main(){
m=qr();n=qr();
for(register int t=1;t<=n;++t)
for(register int i=1;i<=m+t-1;++i){
data[t][i]=-qr(),id[t][i]=++nodecnt,add(id[t][i],++nodecnt,1,data[t][i]);
//cout<<data[t][i]<<' ';
}
S=++nodecnt;
T=++nodecnt;
for(register int t=1;t<=n;++t){
for(register int i=1;i<=m+t-1;++i){
if(id[t+1][i+1]) add(id[t][i]+1,id[t+1][i+1],1,0);
if(id[t+1][i]) add(id[t][i]+1,id[t+1][i],1,0);
//cout<<" qaq="<<id[t][i]<<' '<<id[t+1][i+1]<<' '<<id[t+1][i]<<' ';
}
}
int ans1,ans2,ans3;
ts=++nodecnt;
add(S,ts,m,0);
for(register int t=1;t<=m;++t) {
add(ts,id[1][t],1,0);
//cout<<"to=s "<<ts<<' '<<id[1][t]<<' ';
}
//cout<<endl;
for(register int t=1;t<=m+n-1;++t) {
add(id[n][t]+1,T,inf,0);
//cout<<"id="<<id[n][t]<<' '<<endl;
}
ans1=mincost();
reset();
//cout<<ans1<<endl;
//return 0;
for(register int t=1;t<=n;++t)
for(register int i=1;i<=m+t-1;++i)
add(id[t][i],id[t][i]+1,inf,data[t][i]);
ans2=mincost();
reset();
for(register int t=1;t<=n;++t){
for(register int i=1;i<=m+t-1;++i){
if(id[t+1][i+1]) add(id[t][i]+1,id[t+1][i+1],inf,0);
if(id[t+1][i]) add(id[t][i]+1,id[t+1][i],inf,0);
}
}
ans3=mincost();
printf("%d\n%d\n%d\n",-ans1,-ans2,-ans3);
return 0;
}
博客保留所有权利,谢绝学步园、码迷等不在文首明显处显著标明转载来源的任何个人或组织进行转载!其他文明转载授权且欢迎!