1. 程式人生 > >方格取數(1)

方格取數(1)

min () edge pop flow name for dfs 二分匹配

該題求的是 最大獨立集團權值和 因為所取的點沒有兩點是相鄰的

所以把相鄰點連起來!

由前面二分匹配知 最大獨立集團=頂點數-最小覆蓋點 加上權值也是一樣的

所以最大獨立集團權值和 ==總權值-最小覆蓋點權值和

所以求出最小覆蓋點權值和即可 且=最小割=最大流

奇偶建圖

源點-奇數 奇數和所有相鄰的建圖 偶數 -匯點

最大流=最小割=最小點權覆蓋集=sum-最大點權獨立集!

#include <iostream>
#include <queue>
#include <cstdio>
#include <algorithm>
#include
<cstring> using namespace std; const int maxn = 50+10; const int E_maxn = 50000 + 10; const int INF = 0x3fffffff; struct Edge { int from; int to; int cap; int next; }; struct Edge edge[E_maxn]; int deep[maxn*maxn]; int cur[maxn*maxn]; int k,n,m; int temp[4][2] = {-1,0, 1,0, 0,-1, 0,1}; void
addedge(int from,int to,int cap) { edge[k].from = from; edge[k].to = to; edge[k].cap = cap; edge[k].next = cur[from]; cur[from] = k; k++; edge[k].from = to; edge[k].to = from; edge[k].cap = 0; edge[k].next = cur[to]; cur[to] = k; k++; } int judge(int x,int
y) { if(x>0 && x<=n && y>0 && y<=m) { return 1; } return 0; } bool BFS() { memset(deep,-1,sizeof(deep)); queue<int> Q; Q.push(0); deep[0] = 0; while(!Q.empty()) { int x = Q.front(); Q.pop(); int i; for(i=cur[x]; i!=-1; i=edge[i].next) { int e = edge[i].to; if(deep[e] == -1 && edge[i].cap > 0) { deep[e] = deep[x] + 1; Q.push(e); } } } return deep[n*m+1] != -1; } int DFS(int x,int a) { if(x == n*m+1) { return a; } int flow = 0; for(int i=cur[x]; i!=-1 && flow<a; i=edge[i].next) { int e = edge[i].to; if(deep[x] + 1 == deep[e] && edge[i].cap > 0) { int f = min(edge[i].cap,a-flow); f = DFS(e,f); flow += f; edge[i].cap -= f; edge[i^1].cap += f; } } if(!flow) { deep[x] = -2;//沒有必要再往這個點走了 } return flow; } int Dinic() { int flow = 0; int F=0; while(BFS()) { while(F=DFS(0,INF)) { flow += F; } } return flow; } int main() { while(cin>>n) { int i; int j; memset(cur,-1,sizeof(cur)); k=0; int sum = 0; int num; for(i=1; i<=n; i++) { for(j=1; j<=n; j++) { scanf("%d",&num); sum+=num; if((i+j) % 2 == 0) { addedge(0,(i-1)*n+j,num); for(int z = 0; z<4; z++) { int x = i+temp[z][0]; int y = j+temp[z][1]; if(judge(x,y)) { addedge((i-1)*n+j,(x-1)*n+y,INF); } } } else { addedge((i-1)*n+j,n*n+1,num); } } } int ans = Dinic(); cout<<sum-ans<<endl; } return 0; }

方格取數(1)