http://acm.hdu.edu.cn/showproblem.php?pid=1565
题意:
给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
思路:
最大点权独立集=点权之和-最小点权覆盖集=最小割=最大流
先来看最小点权覆盖集,也就是选取点覆盖所有的边,并且权值要最小。
解决方法是:
从源点向X集连边,容量为点的权值,Y集向汇点连边,容量也为点的权值。如果u和v这两个点相连的话,则将这两个点连一条有向边,容量为INF,因为我们要割的不是这个。这样,从s到t的路径中,就包含了所有的边,最小点覆盖也就是连通所有边,最小割就是让所有边都不连通,于是求个最大流即可。
这样一来,最大点权独立集也就可以求出来了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 typedef long long LL; 8 9 const int maxn=2000+5; 10 const int INF=0x3f3f3f3f; 11 12 struct Edge 13 { 14 int from,to,cap,flow; 15 Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){} 16 }; 17 18 struct Dinic 19 { 20 int n,m,s,t; 21 vector<Edge> edges; 22 vector<int> G[maxn]; 23 bool vis[maxn]; 24 int cur[maxn]; 25 int d[maxn]; 26 27 void init(int n) 28 { 29 this->n=n; 30 for(int i=0;i<n;++i) G[i].clear(); 31 edges.clear(); 32 } 33 34 void AddEdge(int from,int to,int cap) 35 { 36 edges.push_back( Edge(from,to,cap,0) ); 37 edges.push_back( Edge(to,from,0,0) ); 38 m=edges.size(); 39 G[from].push_back(m-2); 40 G[to].push_back(m-1); 41 } 42 43 bool BFS() 44 { 45 queue<int> Q; 46 memset(vis,0,sizeof(vis)); 47 vis[s]=true; 48 d[s]=0; 49 Q.push(s); 50 while(!Q.empty()) 51 { 52 int x=Q.front(); Q.pop(); 53 for(int i=0;i<G[x].size();++i) 54 { 55 Edge& e=edges[G[x][i]]; 56 if(!vis[e.to] && e.cap>e.flow) 57 { 58 vis[e.to]=true; 59 d[e.to]=d[x]+1; 60 Q.push(e.to); 61 } 62 } 63 } 64 return vis[t]; 65 } 66 67 int DFS(int x,int a) 68 { 69 if(x==t || a==0) return a; 70 int flow=0, f; 71 for(int &i=cur[x];i<G[x].size();++i) 72 { 73 Edge &e=edges[G[x][i]]; 74 if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0) 75 { 76 e.flow +=f; 77 edges[G[x][i]^1].flow -=f; 78 flow +=f; 79 a -=f; 80 if(a==0) break; 81 } 82 } 83 return flow; 84 } 85 86 int Maxflow(int s,int t) 87 { 88 this->s=s; this->t=t; 89 int flow=0; 90 while(BFS()) 91 { 92 memset(cur,0,sizeof(cur)); 93 flow +=DFS(s,INF); 94 } 95 return flow; 96 } 97 }DC; 98 99 int n; 100 int map[25][25]; 101 int dx[]={0,0,1,-1}; 102 int dy[]={1,-1,0,0}; 103 104 int main() 105 { 106 while(~scanf("%d",&n)) 107 { 108 int sum=0; 109 int src=0,dst=n*n+1; 110 DC.init(dst+1); 111 for(int i=1;i<=n;i++) 112 for(int j=1;j<=n;j++) 113 { 114 scanf("%d",&map[i][j]); 115 sum+=map[i][j]; 116 } 117 for(int i=1;i<=n;i++) 118 for(int j=1;j<=n;j++) 119 { 120 int id=(i-1)*n+j; 121 int t=(i+j)%2; 122 if(t) 123 { 124 DC.AddEdge(src,id,map[i][j]); 125 for(int k=0;k<4;k++) 126 { 127 int x=dx[k]+i; 128 int y=dy[k]+j; 129 if(x<1||x>n||y<1||y>n) continue; 130 DC.AddEdge(id,(x-1)*n+y,INF); 131 } 132 } 133 else DC.AddEdge(id,dst,map[i][j]); 134 } 135 int ans=DC.Maxflow(src,dst); 136 printf("%d ",sum-ans); 137 } 138 return 0; 139 }