• 【HDOJ5520】Number Link(费用流)


    题意:NxM的格子有些上面有数字,现在要把奇数跟偶数配对连起来,其他的格子连成一个个回路,

    单独的相邻两个格子相连也算是一个回路按两条边算,连线不能相交,

    给出相邻两个格子相连的费用,求最小的总费用,无解输出-1

    n,m<=50

    保证答案在int范围之内

    思路:费用流神仙建模

    From https://blog.csdn.net/ahi219/article/details/51454133

    把每个格子拆成两个点,然后如下连边:

    源点向左边的奇数格子和空格子连容量为1,费用为0的边。

    右边的偶数格子和空格子向汇点连容量为1,费用为0的边。

    左边的格子向右边相邻的格子连容量为1,费用为cost的边。

    这样求一遍最小费用最大流即可,如果不是满流,则为无解。

    这样建模的原因是把每空格子拆成入点和出点,奇数只有入点,偶数只有出点。

    这样保证了每个空格子会有一个入度和一个出度,要么成环,要么参与到奇偶相连中。

    奇数只有出度偶数只有出度保证了一定是奇数连向偶数。

    这样求一遍费用流最后就是结果,如果不是满流说明有的点没连上所以无解。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<string>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<map>
      8 #include<set>
      9 #include<queue>
     10 #include<vector>
     11 using namespace std;
     12 typedef long long ll;
     13 typedef unsigned int uint;
     14 typedef unsigned long long ull;
     15 typedef pair<int,int> PII;
     16 typedef vector<int> VI;
     17 #define fi first
     18 #define se second 
     19 #define MP make_pair
     20 #define N      31000
     21 #define M      51
     22 #define MOD 1000000007
     23 #define eps 1e-8 
     24 #define pi     acos(-1)
     25 #define oo     1010000000
     26 
     27 bool inq[N];
     28 int num[M][M][2],a[M][M],
     29     q[N],dis[N],head[N],vet[N],nxt[N],len1[N],len2[N],fan[N],pre[N][2],
     30     n,source,src,tot,s,ans,flow;
     31     
     32 void add(int a,int b,int c,int d)
     33 {
     34     nxt[++tot]=head[a];
     35     vet[tot]=b;
     36     len1[tot]=c;
     37     len2[tot]=d;
     38     head[a]=tot;
     39     
     40     nxt[++tot]=head[b];
     41     vet[tot]=a;
     42     len1[tot]=0;
     43     len2[tot]=-d;
     44     head[b]=tot;
     45 }
     46 
     47 bool spfa()
     48 {
     49     for(int i=1;i<=s;i++)
     50     {
     51         dis[i]=oo;
     52         inq[i]=false;
     53     }
     54     int t=0; int w=1;
     55     q[1]=source; dis[source]=0; inq[source]=true;
     56     while(t<w)
     57     {
     58         t++; int u=q[t%(s+5)]; inq[u]=false;
     59         int e=head[u];
     60         while(e)
     61         {
     62             int v=vet[e];
     63             if(len1[e]&&dis[u]+len2[e]<dis[v])
     64             {
     65                 dis[v]=dis[u]+len2[e];
     66                 pre[v][1]=u;
     67                 pre[v][2]=e;
     68                 if(!inq[v])
     69                 {
     70                     w++; q[w%(s+5)]=v; inq[v]=true;
     71                 }
     72             }
     73             e=nxt[e];
     74         }
     75     }
     76     return (dis[src]!=oo);
     77 }
     78 
     79 void mcf()
     80 {
     81     int k=src;
     82     int t=oo;
     83     while(k!=source)
     84     {
     85         int e=pre[k][2];
     86         t=min(t,len1[e]);
     87         k=pre[k][1];    
     88     }
     89     k=src;
     90     while(k!=source)
     91     {
     92         int e=pre[k][2];
     93         len1[e]-=t;
     94         len1[fan[e]]+=t;
     95         ans+=t*len2[e];
     96         k=pre[k][1];
     97     }
     98     flow+=t;
     99 }
    100 
    101 void init()
    102 {
    103     memset(head,0,sizeof(head));
    104     memset(pre,0,sizeof(pre));
    105     tot=0;
    106 }
    107 
    108 int main()
    109 { 
    110     freopen("hdoj5520.in","r",stdin);
    111     //freopen("hdoj5520.out","w",stdout);
    112     for(int i=1;i<N;i++)
    113      if(i&1) fan[i]=i+1;
    114       else fan[i]=i-1; 
    115      int cas;
    116      scanf("%d",&cas);
    117      for(int v=1;v<=cas;v++) 
    118      {
    119          int n,m;
    120          scanf("%d%d",&n,&m);
    121          int F=0;
    122          for(int i=1;i<=n;i++)
    123           for(int j=1;j<=m;j++) 
    124           {
    125               scanf("%d",&a[i][j]);
    126               if(a[i][j]==0) F++;
    127               if(a[i][j]&&a[i][j]%2==1) F++;
    128           }    
    129          s=0;
    130          for(int i=1;i<=n;i++)
    131           for(int j=1;j<=m;j++)
    132            for(int k=0;k<=1;k++) num[i][j][k]=++s;
    133          init();
    134          source=s+1; src=s+2; s+=2;
    135          for(int i=1;i<=n;i++)
    136           for(int j=1;j<=m;j++)
    137           {
    138               if(a[i][j]==0||a[i][j]%2==1) add(source,num[i][j][0],1,0);
    139               if(a[i][j]==0||a[i][j]%2==0) add(num[i][j][1],src,1,0);
    140           }
    141          for(int i=1;i<=n-1;i++)
    142           for(int j=1;j<=m;j++)
    143           {
    144               int x;
    145               scanf("%d",&x);
    146              add(num[i][j][0],num[i+1][j][1],1,x);
    147              add(num[i+1][j][0],num[i][j][1],1,x);
    148           }
    149          for(int i=1;i<=n;i++)
    150           for(int j=1;j<=m-1;j++)
    151           {
    152               int x;
    153               scanf("%d",&x);
    154               add(num[i][j][0],num[i][j+1][1],1,x);
    155             add(num[i][j+1][0],num[i][j][1],1,x);
    156          }
    157         ans=0; flow=0;
    158         while(spfa()) mcf();
    159         if(flow==F) printf("Case #%d: %d
    ",v,ans);
    160          else printf("Case #%d: -1
    ",v);
    161     }
    162     return 0;
    163 }
    164     
  • 相关阅读:
    【iOS开发-从网络上获取图片尺寸】
    【iOS开发之静态库、动态库】
    【iOS开发之OC和JS互调】
    【iOS之runtime、runloop】
    【iOS开发之C语言】sprintf,strncpy,strcmp三个函数的区别
    计算机中的存储单位
    linux命令行
    python的安装
    Java的跨平台特性
    方法的重写(override)两同两小一大原则:
  • 原文地址:https://www.cnblogs.com/myx12345/p/10035520.html
Copyright © 2020-2023  润新知