zoukankan      html  css  js  c++  java
  • LOJ #6010. 「网络流 24 题」数字梯形

    #6010. 「网络流 24 题」数字梯形

     

    题目描述

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

    分别遵守以下规则:

    1. 从梯形的顶至底的 m mm 条路径互不相交;
    2. 从梯形的顶至底的 m mm 条路径仅在数字结点处相交;
    3. 从梯形的顶至底的 m mm 条路径允许在数字结点相交或边相交。

    输入格式

    第 1 11 行中有 2 22 个正整数 m mm 和 n nn,分别表示数字梯形的第一行有 m mm 个数字,共有 n nn 行。接下来的 n nn 行是数字梯形中各行的数字。
    第 1 11 行有 m mm 个数字,第 2 22 行有 m+1 m + 1m+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≤m,n≤20 1 leq m, n leq 201m,n20

    code

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 
      5 using namespace std;
      6 const int N = 1010;
      7 const int INF = 1e9;
      8 
      9 struct Edge{
     10     int u,v,f,c,nxt;
     11     Edge(){}
     12     Edge(int a,int b,int flow,int cost,int nt) {
     13         u = a;v = b;f = flow;c = cost;nxt = nt;
     14     }
     15 }e[100100];
     16 int head[N],dis[N],q[100100],pre[N],a[30][30],b[30][30];
     17 bool vis[N];
     18 int n,m,S,T,tn,L,R,Mc,ans,tot;
     19 
     20 inline char nc() {
     21     static char buf[100000],*p1 = buf,*p2 = buf;
     22     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF :*p1++;
     23 }
     24 inline int read() {
     25     int x = 0,f = 1;char ch=nc();
     26     for (; ch<'0'||ch>'9'; ch=nc()) if(ch=='-')f=-1;
     27     for (; ch>='0'&&ch<='9'; ch=nc()) x=x*10+ch-'0';
     28     return x*f;
     29 }
     30 void add_edge(int u,int v,int f,int c) {
     31     e[++tot] = Edge(u,v,f,c,head[u]);head[u] = tot;
     32     e[++tot] = Edge(v,u,0,-c,head[v]);head[v] = tot;
     33 }
     34 bool spfa() {
     35     for (int i=1; i<=T; ++i) vis[i]=false,dis[i]=INF;
     36     L = 1;R = 0;
     37     dis[S] = 0;
     38     q[++R] = S;vis[S] = true;pre[S] = 0;
     39     while (L <= R) {
     40         int u = q[L++];
     41         for (int i=head[u]; i; i=e[i].nxt) {
     42             int v = e[i].v;
     43             if (dis[v]>dis[u]+e[i].c && e[i].f > 0) {
     44                 dis[v] = dis[u] + e[i].c;
     45                 pre[v] = i;
     46                 if (!vis[v]) q[++R] = v,vis[v] = true;
     47             }
     48         }
     49         vis[u] = false;
     50     }
     51     return dis[T]!=INF;
     52 }
     53 void mcf() {
     54     int zf = INF;
     55     for (int i=T; i!=S; i=e[pre[i]].u) 
     56         zf = min(zf,e[pre[i]].f);
     57     for (int i=T; i!=S; i=e[pre[i]].u) 
     58         e[pre[i]].f -= zf,e[pre[i]^1].f += zf;
     59     Mc += dis[T]*zf;
     60 }
     61 int work() {
     62     Mc = 0;
     63     while (spfa()) mcf();
     64     printf("%d
    ",-Mc);
     65 }
     66 void init() {
     67     tot = 1;
     68     memset(head,0,sizeof(head));
     69 }
     70 void build_1() {
     71     init();
     72     S = tn + tn + 1;T = tn + tn + 2;
     73     for (int i=1; i<=n; ++i) 
     74         for (int j=1; j<=m+i-1; ++j) {
     75             add_edge(b[i][j],b[i][j]+tn,1,-a[i][j]);
     76             add_edge(b[i][j]+tn,b[i+1][j],1,0);
     77             add_edge(b[i][j]+tn,b[i+1][j+1],1,0);
     78             if (i==1) add_edge(S,b[i][j],1,0);
     79             if (i==n) add_edge(b[i][j]+tn,T,1,0);
     80         }
     81 }
     82 void build_2() {
     83     init();
     84     S = tn + 1;T = tn + 2;
     85     for (int i=1; i<=n; ++i) {
     86         for (int j=1; j<=m+i-1; ++j) {
     87             add_edge(b[i][j],b[i+1][j],1,-a[i][j]);
     88             add_edge(b[i][j],b[i+1][j+1],1,-a[i][j]);
     89             if (i==1) add_edge(S,b[i][j],1,0);
     90             if (i==n) add_edge(b[i][j],T,INF,-a[i][j]);
     91         }
     92     }
     93 }
     94 void build_3() {
     95     init();
     96     S = tn + 1;T = tn + 2;
     97     for (int i=1; i<=n; ++i) {
     98         for (int j=1; j<=m+i-1; ++j) {
     99             add_edge(b[i][j],b[i+1][j],INF,-a[i][j]);
    100             add_edge(b[i][j],b[i+1][j+1],INF,-a[i][j]);
    101             if (i==1) add_edge(S,b[i][j],1,0);
    102             if (i==n) add_edge(b[i][j],T,INF,-a[i][j]);
    103         }
    104     }
    105 }
    106 int main() {
    107     m = read(),n = read();
    108     for (int i=1; i<=n; ++i) 
    109         for (int j=1; j<=m+i-1; ++j) a[i][j] = read(),b[i][j] = ++tn;
    110 
    111     build_1();work();
    112     build_2();work();
    113     build_3();work();
    114     return 0;
    115 }
  • 相关阅读:
    安装minio单机
    linux使用某非root用户执行开机启动项
    Maven Plugin fork 在 pom.xml中的作用
    Sourcetree 使用之 git add, git commit, git push, git reset commit
    idea远程debug k8s容器服务
    WebService Client端
    Maven编译外部jar包问题
    Sourcetree 使用之 git stash save 和 git stash pop
    Sybase 相关
    FW300R手机不能上网解决方法
  • 原文地址:https://www.cnblogs.com/mjtcn/p/8542325.html
Copyright © 2011-2022 走看看