hdu - 1565 方格取数(1) && 1569 方格取数(2) (最大点权独立集)

http://acm.hdu.edu.cn/showproblem.php?pid=1565

两道题只是数据范围不同,都是求的最大点权独立集.

我们可以把下标之和为奇数的分成一个集合,把下标之和为偶数的分成一个集合,然后构造一个源点向其中一个集合连边,另一个集合向汇点连边.权值都为P[i][j].

然后由源点指向的集合向指向汇点的集合连边权值为INF.这样跑一遍就是最小点权覆盖.

那么最大点权独立集=总权-最小点权覆盖=总权-最大流.

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cmath>
  4 #include <vector>
  5 #include <cstring>
  6 #include <string>
  7 #include <algorithm>
  8 #include <string>
  9 #include <set>
 10 #include <functional>
 11 #include <numeric>
 12 #include <sstream>
 13 #include <stack>
 14 #include <map>
 15 #include <queue>
 16 #pragma comment(linker, "/STACK:102400000,102400000")
 17 #define CL(arr, val)    memset(arr, val, sizeof(arr))
 18 
 19 #define ll long long
 20 #define inf 0x7f7f7f7f
 21 #define lc l,m,rt<<1
 22 #define rc m + 1,r,rt<<1|1
 23 #define pi acos(-1.0)
 24 
 25 #define L(x)    (x) << 1
 26 #define R(x)    (x) << 1 | 1
 27 #define MID(l, r)   (l + r) >> 1
 28 #define Min(x, y)   (x) < (y) ? (x) : (y)
 29 #define Max(x, y)   (x) < (y) ? (y) : (x)
 30 #define E(x)        (1 << (x))
 31 #define iabs(x)     (x) < 0 ? -(x) : (x)
 32 #define OUT(x)  printf("%I64d\n", x)
 33 #define lowbit(x)   (x)&(-x)
 34 #define Read()  freopen("a.txt", "r", stdin)
 35 #define Write() freopen("b.txt", "w", stdout);
 36 #define maxn 1010
 37 #define maxv 100000
 38 #define mod 1000000000
 39 using namespace std;
 40 
 41 struct edge
 42 {
 43     int to,cap,rev;
 44     edge(){}
 45     edge(int x,int y,int z)
 46     {
 47         to=x;
 48         cap=y;
 49         rev=z;
 50     }
 51 };
 52 
 53 vector<edge>G[maxv];
 54 int level[maxv];
 55 int iter[maxv];
 56 
 57 void Add_Edge(int from,int to,int cap)
 58 {
 59     G[from].push_back((edge){to,cap,G[to].size()});
 60     G[to].push_back((edge){from,0,G[from].size()-1});
 61 }
 62 
 63 void bfs(int s)
 64 {
 65     memset(level,-1,sizeof(level));
 66     queue<int>que;
 67     level[s]=0;
 68     que.push(s);
 69     while(!que.empty())
 70     {
 71         int v=que.front();que.pop();
 72         for(int i=0;i<G[v].size();i++)
 73         {
 74             edge &e=G[v][i];
 75             if(e.cap>0&&level[e.to]<0)
 76             {
 77                 level[e.to]=level[v]+1;
 78                 que.push(e.to);
 79             }
 80         }
 81     }
 82 }
 83 int dfs(int v,int t,int f)
 84 {
 85     if(v==t) return f;
 86     for(int &i=iter[v];i<G[v].size();i++)
 87     {
 88         edge &e=G[v][i];
 89         if(e.cap>0&&level[v]<level[e.to])
 90         {
 91             int d=dfs(e.to,t,min(f,e.cap));
 92             if(d>0)
 93             {
 94                 e.cap-=d;
 95                 G[e.to][e.rev].cap+=d;
 96               //  printf("%d %d %d\n",e.to,e.rev,G[e.to][e.rev]);
 97                 return d;
 98             }
 99         }
100     }
101     return 0;
102 }
103 
104 int max_flow(int s,int t)
105 {
106     int flow=0;
107     for(;;)
108     {
109         bfs(s);
110         if(level[t]<0) return flow;
111         memset(iter,0,sizeof(iter));
112         int f;
113         while((f=dfs(s,t,inf))>0)
114         flow+=f;
115     }
116 }
117 int s[55][55];
118 int n,m;
119 int ID(int i,int j)
120 {
121     return i*m+j;
122 }
123 int main()
124 {
125    //freopen("a.txt","r",stdin);
126     int sum;
127     while(~scanf("%d%d",&n,&m))
128     {
129         for(int i=0;i<n*m+2;i++) G[i].clear();
130         sum=0;
131         for(int i=0;i<n;i++)
132         {
133             for(int j=0;j<m;j++)
134             {
135                 scanf("%d",&s[i][j]);
136                 sum+=s[i][j];
137             }
138         }
139         for(int i=0;i<n;i++)
140         {
141             for(int j=0;j<m;j++)
142             {
143                if((i+j)%2)
144                {
145                    Add_Edge(n*m,ID(i,j),s[i][j]);
146                    if(i>0) Add_Edge(ID(i,j),ID(i-1,j),inf);
147                    if(j>0) Add_Edge(ID(i,j),ID(i,j-1),inf);
148                    if(i<n-1) Add_Edge(ID(i,j),ID(i+1,j),inf);
149                    if(j<m-1) Add_Edge(ID(i,j),ID(i,j+1),inf);
150                }
151                else
152                {
153                    Add_Edge(ID(i,j),n*m+1,s[i][j]);
154                   // if(i>0) Add_Edge(ID(i,j),ID(i-1,j),inf);
155                   // if(j>0) Add_Edge(ID(i,j),ID(i,j-1),inf);
156                    //if(i<n-1) Add_Edge(ID(i,j),ID(i+1,j),inf);
157                    //if(j<n-1) Add_Edge(ID(i,j),ID(i,j+1),inf);
158                }
159             }
160         }
161         printf("%d\n",sum-max_flow(n*m,n*m+1));
162     }
163     return 0;
164 }

 

转载于:https://www.cnblogs.com/nowandforever/p/4606706.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值