您的位置:首页 > 理论基础 > 计算机网络

[网络流24题] 数字梯形问题

2018-02-19 21:29 477 查看
题面:

传送门

思路:

三合一题目

但是实际上做好了第一个就没有别的问题了

第一问:

把每个数字拆成两个点,中间连一条容量为1,费用为0的边,以此达到限制每个点流量的目的

然后其余的不多说,源点到第一层,每一层向下连,最后一层到汇点

第二问:

第一问中每个点内部的那条边容量改成inf就好

第三问:

直接dp算了......当然你也可以再改改边,跑网络流,不过估计没有dp快

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 1000000000
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re;
}
int n,m,cnt,ans,flow,tot,first[10010],x[25][25],id[25][25];
int dis[10010],pre[10010],path[10010];
struct edge{
int to,next,w,cap;
}a[100010];
inline void add(int u,int v,int w,int cap){
//    cout<<"add "<<u<<ends<<v<<ends<<w<<ends<<cap<<endl;
a[++cnt]=(edge){v,first[u],w,cap};first[u]=cnt;
a[++cnt]=(edge){u,first[v],-w,0};first[v]=cnt;
}
void init(){
memset(first,-1,sizeof(first));
memset(a,0,sizeof(a));cnt=-1;ans=0;flow=0;
}
int spfa(int s,int t){
int q[10010],head=0,tail=1,maxn=10000,i,u,v,w;
memset(pre,-1,sizeof(pre));
for(i=s;i<=t;i++) dis[i]=inf;
q[0]=s;dis[s]=0;
while(head!=tail){
u=q[head];head=(head+1)%maxn;
//        cout<<"spfa "<<u<<endl;
for(i=first[u];~i;i=a[i].next){
v=a[i].to;w=a[i].w;
//            cout<<"    to "<<v<<ends<<dis[v]<<ends<<w+dis[u]<<endl;
if(a[i].cap&&dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
pre[v]=u;path[v]=i;
q[tail]=v;tail=(tail+1)%maxn;
}
}
}
return ~pre[t];
}
inline int _min(int l,int r){return (l<r)?l:r;}
int mcmf(int s,int t){
int f,u;
while(spfa(s,t)){
f=inf;
for(u=t;u!=s;u=pre[u]) f=_min(f,a[path[u]].cap);
flow+=f;ans+=dis[t]*f;
//        cout<<"mcmf "<<flow<<ends<<ans<<endl;
for(u=t;u!=s;u=pre[u]){
a[path[u]].cap-=f;
a[path[u]^1].cap+=f;
}
}
}
int main(){
freopen("digit.in","r",stdin);
freopen("digit.out","w",stdout);
int i,j;
n=read();m=read();
for(i=1;i<=m;i++){
for(j=1;j<=i+n-1;j++) x[i][j]=read(),id[i][j]=++tot;
}
//T1
init();
for(i=1;i<=n;i++) add(0,id[1][i],0,1);
for(i=1;i<=m;i++){
for(j=1;j<=i+n-1;j++) add(id[i][j],id[i][j]+tot,0,1);
}
for(i=1;i<m;i++){
for(j=1;j<=i+n-1;j++){
add(id[i][j]+tot,id[i+1][j],-x[i][j],1);
add(id[i][j]+tot,id[i+1][j+1],-x[i][j],1);
}
}
for(i=1;i<=n+m-1;i++) add(id[m][i]+tot,(tot<<1)+1,-x[m][i],1);
mcmf(0,(tot<<1)+1);
printf("%d\n",-ans);
//T2
init();
for(i=1;i<=n;i++) add(0,id[1][i],0,1);
for(i=1;i<=m;i++){
for(j=1;j<=i+n-1;j++) add(id[i][j],id[i][j]+tot,0,inf);
}
for(i=1;i<m;i++){
for(j=1;j<=i+n-1;j++){
add(id[i][j]+tot,id[i+1][j],-x[i][j],1);
add(id[i][j]+tot,id[i+1][j+1],-x[i][j],1);
}
}
for(i=1;i<=n+m-1;i++) add(id[m][i]+tot,(tot<<1)+1,-x[m][i],inf);
mcmf(0,(tot<<1)+1);
printf("%d\n",-ans);
//T3
init();
for(i=1;i<=n;i++) add(0,id[1][i],0,1);
for(i=1;i<=m;i++){
for(j=1;j<=i+n-1;j++) add(id[i][j],id[i][j]+tot,0,inf);
}
for(i=1;i<m;i++){
for(j=1;j<=i+n-1;j++){
add(id[i][j]+tot,id[i+1][j],-x[i][j],inf);
add(id[i][j]+tot,id[i+1][j+1],-x[i][j],inf);
}
}
for(i=1;i<=n+m-1;i++) add(id[m][i]+tot,(tot<<1)+1,-x[m][i],inf);
mcmf(0,(tot<<1)+1);
printf("%d",-ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: