[hdu1569]方格取數(2) 最大點權獨立集
阿新 • • 發佈:2019-02-10
題目大意:給你一個m*n的格子的棋盤,每個格子裡面有一個非負數。
從中取出若干個數,使得任意的兩個數所在的格子沒有公共邊,就是說所取數所在的2個格子不能相鄰,並且取出的數的和最大。
我們首先將棋盤染成二色圖(相鄰點顏色不同),再將它想象成二分圖。
設立一個超級源點與超級匯點,將超級源點與一種顏色相連,另一種顏色與超級匯點相連,容量為格子權值。
再將將相鄰的異色格(從連線超級源點的格子到連線超級匯點的格子)之間建立一條容量無限大的邊。
我們就可以看出,題目要求求出二分圖的最大點權獨立集,將其轉為二分圖最小點權覆蓋問題(戳我)。
#include <cstdio> #include <cstring> #include <vector> #include <queue> #define inf 1e9 using namespace std; int m,n; int map[55][55]; struct Edge{ int to,flow,ro; }; vector<Edge> e; vector<int> g[2505]; int dis[2505]; bool vis[2505]; int cur[2505]; int tot; int s,ed; void add_edge(int from,int to,int ro) { e.push_back((Edge){to,0,ro}); g[from].push_back(tot); tot++; e.push_back((Edge){from,0,0}); g[to].push_back(tot); tot++; } void build_edge() { register int i,j; for (i=1;i<=n;i++) { for (j=1;j<=m;j++) { int now=(i-1)*m+j; if ((i+j)%2) { add_edge(s,now,map[i][j]); if(i>1) add_edge(now,now-m,inf); if(i<n) add_edge(now,now+m,inf); if(j>1) add_edge(now,now-1,inf); if(j<m) add_edge(now,now+1,inf); } else add_edge(now,ed,map[i][j]); } } } bool bfs(int s,int ed) { register int i; memset(vis,0,sizeof (vis)); queue<int>q; q.push(s); vis[s]=1;dis[s]=0; while (!q.empty()) { int x=q.front(); q.pop(); for (i=0;i<g[x].size();i++) { Edge& ee=e[g[x][i]]; if (!vis[ee.to]&&ee.ro>ee.flow) { vis[ee.to]=1; dis[ee.to]=dis[x]+1; q.push(ee.to); } } } return vis[ed]; } int dfs(int x,int a) { if (x==ed||a==0) return a; int flow=0,f; for (int& i=cur[x];i<g[x].size();i++) { Edge& ee=e[g[x][i]]; if(dis[x]+1==dis[ee.to]&&(f=dfs(ee.to,min(a,ee.ro-ee.flow)))>0) { ee.flow+=f; e[g[x][i]^1].flow-=f; flow+=f; a-=f; if (a==0) break; } } return flow; } int dinic(int s,int ed) { int flow=0; while (bfs(s,ed)) { memset(cur,0,sizeof(cur)); flow+=dfs(s,inf); } return flow; } int main() { register int i,j; while(~scanf("%d%d",&n,&m)) { memset(dis,0,sizeof(dis)); for (i=0;i<=2503;i++) { g[i].clear(); } e.clear(); tot=0; int re=0; for (i=1;i<=n;i++) for (j=1;j<=m;j++) { scanf("%d",&map[i][j]); re+=map[i][j]; } s=0,ed=n*m+1; build_edge(); printf("%d\n",re-dinic(s,ed)); } return 0; }