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 }