• 【刷题】LOJ 6010 「网络流 24 题」数字梯形


    题目描述

    给定一个由 (n) 行数字组成的数字梯形如下图所示。梯形的第一行有 (m) 个数字。从梯形的顶部的 (m) 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。

    分别遵守以下规则:

    1. 从梯形的顶至底的 (m) 条路径互不相交;

    2. 从梯形的顶至底的 (m) 条路径仅在数字结点处相交;

    3. 从梯形的顶至底的 (m) 条路径允许在数字结点相交或边相交。

    输入格式

    (1) 行中有 (2) 个正整数 (m)(n),分别表示数字梯形的第一行有 (m) 个数字,共有 (n) 行。接下来的 (n) 行是数字梯形中各行的数字。

    (1) 行有 (m) 个数字,第 (2) 行有 (m + 1) 个数字 ……

    输出格式

    将按照规则 1,规则 2,和规则 3 计算出的最大数字总和并输出,每行一个最大总和。

    样例

    样例输入

    2 5
    2 3
    3 4 5
    9 10 9 1
    1 1 10 1 1
    1 1 10 12 1 1
    

    样例输出

    66
    75
    77
    

    数据范围与提示

    (1 leq m, n leq 20)

    题解

    对于规则一,点和边都只能经过一次,那么拆点,之间连容量为 (1) 的边,点与点之间的边容量也为 (1)

    对于规则二,即点可以经过多次,那么把拆点后之间的边的容量改为 (inf) 就可以了

    对于规则三,在规则二的基础上,把点与点之间的边改为 (inf) 即可

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=1200+10,MAXM=MAXN*MAXN+10,inf=0x3f3f3f3f;
    int n,m,G[MAXN][MAXN],e,beg[MAXN],cur[MAXN],level[MAXN],p[MAXN],to[MAXM<<1],nex[MAXM<<1],cap[MAXM<<1],was[MAXM<<1],vis[MAXN],clk,s,t,all;
    ll answas;
    std::queue<int> q;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline int id(int x,int y)
    {
    	return (n+n+x-2)*(x-1)/2+y;
    }
    inline void insert(int x,int y,int z,int k)
    {
    	to[++e]=y;
    	nex[e]=beg[x];
    	beg[x]=e;
    	cap[e]=z;
    	was[e]=k;
    	to[++e]=x;
    	nex[e]=beg[y];
    	beg[y]=e;
    	cap[e]=0;
    	was[e]=-k;
    }
    inline void build(int ft,int sd)
    {
    	e=1;memset(beg,0,sizeof(beg));answas=0;
    	for(register int i=1;i<=n;++i)insert(s,id(1,i),1,-G[1][i]);
    	for(register int i=1;i<=all;++i)insert(i,i+all,ft?inf:1,0);
    	for(register int i=1;i<m;++i)
    		for(register int j=1;j<=n+i-1;++j)
    		{
    			insert(id(i,j)+all,id(i+1,j),sd?inf:1,-G[i+1][j]);
    			insert(id(i,j)+all,id(i+1,j+1),sd?inf:1,-G[i+1][j+1]);
    		}
    	for(register int i=1;i<=n+m-1;++i)insert(id(m,i)+all,t,ft||sd?inf:1,0);
    }
    inline bool bfs()
    {
    	memset(level,inf,sizeof(level));
    	level[s]=0;
    	p[s]=1;
    	q.push(s);
    	while(!q.empty())
    	{
    		int x=q.front();
    		q.pop();
    		p[x]=0;
    		for(register int i=beg[x];i;i=nex[i])
    			if(cap[i]&&level[to[i]]>level[x]+was[i])
    			{
    				level[to[i]]=level[x]+was[i];
    				if(!p[to[i]])p[to[i]]=1,q.push(to[i]);
    			}
    	}
    	return level[t]!=inf;
    }
    inline int dfs(int x,int maxflow)
    {
    	if(x==t||!maxflow)return maxflow;
    	vis[x]=clk;
    	int res=0;
    	for(register int &i=cur[x];i;i=nex[i])
    		if((vis[to[i]]^vis[x])&&cap[i]&&level[to[i]]==level[x]+was[i])
    		{
    			int f=dfs(to[i],min(maxflow,cap[i]));
    			cap[i]-=f;
    			cap[i^1]+=f;
    			res+=f;
    			answas+=1ll*f*was[i];
    			maxflow-=f;
    			if(!maxflow)break;
    		}
    	vis[x]=0;
    	return res;
    }
    inline int MCMF()
    {
    	int res=0;
    	while(bfs())clk++,memcpy(cur,beg,sizeof(cur)),res+=dfs(s,inf);
    	return res;
    }
    int main()
    {
    	read(n);read(m);
    	all=(n+n+m-1)*m/2,s=all+all+1,t=s+1;
    	for(register int i=1;i<=m;++i)
    		for(register int j=1;j<=n+i-1;++j)read(G[i][j]);
    	build(0,0);MCMF();write(-answas,'
    ');
    	build(1,0);MCMF();write(-answas,'
    ');
    	build(1,1);MCMF();write(-answas,'
    ');
    	return 0;
    }
    
  • 相关阅读:
    素数
    Java日期时间使用(转)
    mysql中函数(转)
    java环境配置
    volley三种基本请求图片的方式与Lru的基本使用:正常的加载+含有Lru缓存的加载+Volley控件networkImageview的使用
    Volley的三种基本用法StringRequest的Get和post用法以及JsonObjectRequest
    DOM生成&解析
    Pull生成&解析
    HDU.2503 a/b + c/d (分式化简)
    HDU.2503 a/b + c/d (分式化简)
  • 原文地址:https://www.cnblogs.com/hongyj/p/9432942.html
Copyright © 2020-2023  润新知