• 【PowerOJ1744&网络流24题】方格取数问题(最小割)


    题意:

     n,m<=30

    思路:

    【问题分析】

    二分图点权最大独立集,转化为最小割模型,从而用最大流解决。

    【建模方法】

    首先把棋盘黑白染色,使相邻格子颜色不同,所有黑色格子看做二分图X集合中顶点,白色格子看做Y集合顶点,建立附加源S汇T。

    1、从S向X集合中每个顶点连接一条容量为格子中数值的有向边。

    2、从Y集合中每个顶点向T连接一条容量为格子中数值的有向边。

    3、相邻黑白格子Xi,Yj之间从Xi向Yj连接一条容量为无穷大的有向边。

    求出网络最大流,要求的结果就是所有格子中数值之和减去最大流量。

    【建模分析】

    这是一个二分图最大点权独立集问题,就是找出图中一些点,使得这些点之间没有边相连,这些点的权值之和最大。独立集与覆盖集是互补的,求最大点权独立集可以转化为求最小点权覆盖集(最小点权

    支配集)。最小点权覆盖集问题可以转化为最小割问题解决。结论:最大点权独立集 = 所有点权 - 最小点权覆盖集 = 所有点权 - 最小割集 = 所有点权 - 网络最大流。

    对于一个网络,除去冗余点(不存在一条ST路径经过的点),每个顶点都在一个从S到T的路径上。割的性质就是不存在从S到T的路径,简单割可以认为割边关联的非ST节点为割点,而在二分图网络流模

    型中每个点必关联到一个割点(否则一定还有增广路,当前割不成立),所以一个割集对应了一个覆盖集(支配集)。最小点权覆盖集就是最小简单割,求最小简单割的建模方法就是把XY集合之间的变容

    量设为无穷大,此时的最小割就是最小简单割了。

    有关二分图最大点权独立集问题,更多讨论见《最小割模型在信息学竞赛中的应用》作者胡伯涛。

      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],len[N],nxt[N],dis[N],
     35     a[50][50],b[50][50],num[50][50],s,S,T,tot;
     36 
     37 int read()
     38 {
     39    int v=0,f=1;
     40    char c=getchar();
     41    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     42    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     43    return v*f;
     44 }
     45 
     46 void add(int a,int b,int c)
     47 {
     48     nxt[++tot]=head[a];
     49     vet[tot]=b;
     50     len[tot]=c;
     51     head[a]=tot;
     52 
     53     nxt[++tot]=head[b];
     54     vet[tot]=a;
     55     len[tot]=0;
     56     head[b]=tot;
     57 }
     58 
     59 bool bfs()
     60 {
     61     queue<int>q;
     62     rep(i,1,s) dis[i]=-1;
     63     q.push(S),dis[S]=0;
     64     while(!q.empty())
     65     {
     66         int u=q.front();
     67         q.pop();
     68         int e=head[u];
     69         while(e)
     70         {
     71             int v=vet[e];
     72             if(len[e]&&dis[v]==-1)
     73             {
     74                 dis[v]=dis[u]+1;
     75                 q.push(v);
     76             }
     77             e=nxt[e];
     78         }
     79     }
     80     return dis[T]!=-1;
     81 }
     82 
     83 int dfs(int u,int aug)
     84 {
     85     if(u==T) return aug;
     86     int e=head[u],val=0,flow=0;
     87     while(e)
     88     {
     89         int v=vet[e];
     90         if(len[e]&&dis[v]==dis[u]+1)
     91         {
     92             int t=dfs(v,min(len[e],aug));
     93             if(!t)
     94             {
     95                 e=nxt[e];
     96                 continue;
     97             }
     98             flow+=t;
     99             aug-=t;
    100             len[e]-=t;
    101             len[e^1]+=t;
    102             if(!aug) break;
    103         }
    104         e=nxt[e];
    105     }
    106     if(!flow) dis[u]=-1;
    107     return flow;
    108 }
    109 
    110 int maxflow()
    111 {
    112     int res=0;
    113     while(bfs()) res+=dfs(S,INF);
    114     return res;
    115 }
    116 
    117 int main()
    118 {
    119     int n=read(),m=read();
    120     int ans=0;
    121     rep(i,1,n)
    122      rep(j,1,m)
    123      {
    124          a[i][j]=read();
    125          ans+=a[i][j];
    126      }
    127 
    128     tot=1;
    129     s=0;
    130     rep(i,1,n)
    131      rep(j,1,m) num[i][j]=++s;
    132 
    133     rep(i,1,n)
    134      rep(j,1,m)
    135       if((i+j+1)&1)
    136        rep(k,0,3)
    137        {
    138             int x=i+dx[k],y=j+dy[k];
    139             if(x>0&&x<=n&&y>0&&y<=m) add(num[i][j],num[x][y],INF);
    140        }
    141     S=++s,T=++s;
    142     rep(i,1,n)
    143      rep(j,1,m)
    144       if((i+j+1)&1) add(S,num[i][j],a[i][j]);
    145        else add(num[i][j],T,a[i][j]);
    146     ans-=maxflow();
    147     printf("%d
    ",ans);
    148     return 0;
    149 }
  • 相关阅读:
    我把问烂了的⭐MySQL⭐面试题总结了一下(带答案,万字总结,精心打磨,建议收藏)
    在高并发情况下我是这样解决单用户超领优惠券问题
    js 数组去重十几种解法,基础知识扎实吗?(附数组方法)
    Jackson 解析 JSON 详细教程
    解锁各种js数组骚操作,总有你想要的!
    JS 异步编程的 5 种解决方案
    YARN 架构设计 和 RPC 网络通信
    基于消息队列构建实时大数据日志分析系统_没用
    Java:List转Map (用stream实现)
    Java时间格式:yyyymmdd转换为yyyy年mm月dd日
  • 原文地址:https://www.cnblogs.com/myx12345/p/11759266.html
Copyright © 2020-2023  润新知