• 【PowerOJ1751&网络流24题】数字梯形问题(费用流)


    题意:

     思路:

    【问题分析】

    求图的最大权不相交路径及其变种,用费用最大流解决。

    【建模方法】

    规则(1)

    把梯形中每个位置抽象为两个点<i.a>,<i.b>,建立附加源S汇T。

    1、对于每个点i从<i.a>到<i.b>连接一条容量为1,费用为点i权值的有向边。

    2、从S向梯形顶层每个<i.a>连一条容量为1,费用为0的有向边。

    3、从梯形底层每个<i.b>向T连一条容量为1,费用为0的有向边。

    4、对于每个点i和下面的两个点j,分别连一条从<i.b>到<j.a>容量为1,费用为0的有向边。

    求最大费用最大流,费用流值就是结果。

    规则(2)

    把梯形中每个位置看做一个点i,建立附加源S汇T。

    1、从S向梯形顶层每个i连一条容量为1,费用为0的有向边。

    2、从梯形底层每个i向T连一条容量为无穷大,费用为0的有向边。

    3、对于每个点i和下面的两个点j,分别连一条从i到j容量为1,费用为点i权值的有向边。

    求最大费用最大流,费用流值就是结果。

    规则(3)

    把梯形中每个位置看做一个点i,建立附加源S汇T。

    1、从S向梯形顶层每个i连一条容量为1,费用为0的有向边。

    2、从梯形底层每个i向T连一条容量为无穷大,费用为0的有向边。

    3、对于每个点i和下面的两个点j,分别连一条从i到j容量为无穷大,费用为点i权值的有向边。

    求最大费用最大流,费用流值就是结果。

    【建模分析】

    对于规则1,要求路径完全不相交,也就是每个点最多只能被访问了一次,所以要把点拆分,之间连接容量为1的边。因为任意一条ST之间的路径都是一个解,在拆分的点内部的边费用设为点的权值,求

    最大费用最大流就是费用最大的m条路经。

    对于规则2,要求路径可以相交,但不能有重叠,此时可以不必拆点了。为了保证路径没有重叠,需要在相邻的两个点上限制流量为1,由于顶层的每个点只能用1次,S向顶层点流量限制也为1。费用只需

    设在相邻点的边上,求最大费用最大流即可。

    对于规则3,要求路径除了顶层每个点以外可以任意相交重叠。在规则2的基础上,取消除S到顶层顶点之间的边以外所有边的流量限制即可。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 typedef unsigned int uint;
      5 typedef unsigned long long ull;
      6 typedef long double ld;
      7 typedef pair<int,int> PII;
      8 typedef pair<ll,ll> Pll;
      9 typedef vector<int> VI;
     10 typedef vector<PII> VII;
     11 typedef pair<ll,ll>P;
     12 #define N  100010
     13 #define M  1000000
     14 #define INF 1e9
     15 #define fi first
     16 #define se second
     17 #define MP make_pair
     18 #define pb push_back
     19 #define pi acos(-1)
     20 #define mem(a,b) memset(a,b,sizeof(a))
     21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
     22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
     23 #define lowbit(x) x&(-x)
     24 #define Rand (rand()*(1<<16)+rand())
     25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
     26 #define ls p<<1
     27 #define rs p<<1|1
     28 
     29 const ll MOD=1e9+7,inv2=(MOD+1)/2;
     30       double eps=1e-6;
     31       int dx[4]={-1,1,0,0};
     32       int dy[4]={0,0,-1,1};
     33 
     34 int head[N],vet[N],len1[N],len2[N],nxt[N],dis[N],q[N],inq[N],a[50][50],
     35     num[50][50][2],pre[N][2],s,S,T,tot,ans1,ans2,n,m;
     36 
     37 
     38 
     39 int read()
     40 {
     41    int v=0,f=1;
     42    char c=getchar();
     43    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     44    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     45    return v*f;
     46 }
     47 
     48 void add(int a,int b,int c,int d)
     49 {
     50     nxt[++tot]=head[a];
     51     vet[tot]=b;
     52     len1[tot]=c;
     53     len2[tot]=d;
     54     head[a]=tot;
     55 
     56     nxt[++tot]=head[b];
     57     vet[tot]=a;
     58     len1[tot]=0;
     59     len2[tot]=-d;
     60     head[b]=tot;
     61 }
     62 
     63 int spfa()
     64 {
     65     rep(i,1,s)
     66     {
     67         dis[i]=-INF;
     68         inq[i]=0;
     69     }
     70     int t=0,w=1;
     71     q[1]=S; dis[S]=0; inq[S]=1;
     72     while(t<w)
     73     {
     74         t++; int u=q[t%(s+5)]; inq[u]=0;
     75         int e=head[u];
     76         while(e)
     77         {
     78             int v=vet[e];
     79             if(len1[e]&&dis[u]+len2[e]>dis[v])
     80             {
     81                 dis[v]=dis[u]+len2[e];
     82                 pre[v][0]=u;
     83                 pre[v][1]=e;
     84                 if(!inq[v])
     85                 {
     86                     w++; q[w%(s+5)]=v; inq[v]=1;
     87                 }
     88             }
     89             e=nxt[e];
     90         }
     91     }
     92     if(dis[T]==-INF) return 0;
     93     return 1;
     94 }
     95 
     96 void mcf()
     97 {
     98     int k=T;
     99     int t=INF;
    100     while(k!=S)
    101     {
    102         int e=pre[k][1];
    103         t=min(t,len1[e]);
    104         k=pre[k][0];
    105     }
    106     ans1+=t;
    107     k=T;
    108     while(k!=S)
    109     {
    110         int e=pre[k][1];
    111         len1[e]-=t;
    112         len1[e^1]+=t;
    113         ans2+=t*len2[e];
    114         k=pre[k][0];
    115     }
    116 }
    117 
    118 void solve1()
    119 {
    120     tot=1;
    121     rep(i,1,s) head[i]=0;
    122     rep(i,1,m) add(S,num[1][i][0],1,0);
    123     rep(i,1,n-1)
    124      rep(j,1,m+i-1)
    125      {
    126          add(num[i][j][1],num[i+1][j][0],1,0);
    127          add(num[i][j][1],num[i+1][j+1][0],1,0);
    128      }
    129     rep(i,1,n)
    130      rep(j,1,m+i-1) add(num[i][j][0],num[i][j][1],1,a[i][j]);
    131     rep(i,1,n+m-1) add(num[n][i][1],T,1,0);
    132     ans1=ans2=0;
    133     while(spfa()) mcf();
    134     printf("%d
    ",ans2);
    135 }
    136 
    137 void solve2()
    138 {
    139     tot=1;
    140     rep(i,1,s) head[i]=0;
    141     rep(i,1,m) add(S,num[1][i][0],1,0);
    142     rep(i,1,n-1)
    143      rep(j,1,m+i-1)
    144      {
    145          add(num[i][j][0],num[i+1][j][0],1,a[i][j]);
    146          add(num[i][j][0],num[i+1][j+1][0],1,a[i][j]);
    147      }
    148     rep(i,1,n+m-1) add(num[n][i][0],T,INF,a[n][i]);
    149     ans1=ans2=0;
    150     while(spfa()) mcf();
    151     printf("%d
    ",ans2);
    152 }
    153 
    154 void solve3()
    155 {
    156     tot=1;
    157     rep(i,1,s) head[i]=0;
    158     rep(i,1,m) add(S,num[1][i][0],1,0);
    159     rep(i,1,n-1)
    160      rep(j,1,m+i-1)
    161      {
    162          add(num[i][j][0],num[i+1][j][0],INF,a[i][j]);
    163          add(num[i][j][0],num[i+1][j+1][0],INF,a[i][j]);
    164      }
    165     rep(i,1,n+m-1) add(num[n][i][0],T,INF,a[n][i]);
    166     ans1=ans2=0;
    167     while(spfa()) mcf();
    168     printf("%d
    ",ans2);
    169 }
    170 
    171 int main()
    172 {
    173     //freopen("1.in","r",stdin);
    174     m=read(),n=read();
    175     s=0;
    176     rep(i,1,n)
    177      rep(j,1,m+i-1)
    178      {
    179          a[i][j]=read();
    180          num[i][j][0]=++s;
    181          num[i][j][1]=++s;
    182      }
    183     S=++s,T=++s;
    184     solve1();
    185     solve2();
    186     solve3();
    187     return 0;
    188 }
  • 相关阅读:
    mysql分表那些事
    java根据经纬度计算距离
    java Calendar类的使用
    mysql中DATETIME、DATE和TIMESTAMP的区别
    java设计模式
    dubbo教程
    Java算法
    随机产生字符串
    js根据类名获取元素的底层原理
    元素样式的获取
  • 原文地址:https://www.cnblogs.com/myx12345/p/11761880.html
Copyright © 2020-2023  润新知