【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 }
原文地址:https://www.cnblogs.com/myx12345/p/11759266.html