/* 和1565一样: 总点数的权 - 最小覆盖点集 = 最大独立集 -------------------------------------- void add(int u, int v, int f)加边 { e[ct].u = u; e[ct].v = v; e[ct].f = f; next[ct] = first[u]; first[u] = ct++; e[ct].u = v; e[ct].v = u; e[ct].f = 0; next[ct] = first[v]; first[v] = ct++; } -------------------------------------- memset(p,-1,sizeof(p);??????? -------------------------------------- for(int i=first[u]; i!=-1; i=next[i]) { if(!a[e[i].v]&&e[i].f)找新结点e[i].v { p[e[i].v]=i;记录e[i].v的父亲 a[e[i].v]=min(a[u],e[i].f);s-e[i].v路径上的最小残量和 q.push(e[i].v);父亲加入队列 } } -------------------------------------- for(int u=t; u!=s; u=e[p[u]].u)从汇点往回用走 { e[p[u]].f-=a[t]; e[p[u]^1].f+=a[t];异或的作用 } -------------------------------------- 建图,题目的关键。。用奇偶建立二分图 代码理解: for(int i=1; i<=m; i++) { for(int j=1; j<=n; j++) { int tmp=(i-1)*n+j;格子从1.....n*m编号,tmp是格子的编号 if((i+j)%2==0)偶数 { add(s,tmp,g[i][j]);与源点相连 if(i>1) add(tmp,(i-2)*n+j,INF); if(i<m) add(tmp,i*n+j,INF); if(j>1) add(tmp,(i-1)*n+j-1,INF); if(j<n) add(tmp,(i-1)*n+j+1,INF); } else add(tmp,t,g[i][j]);与汇点 } } --------------------------------- */ #include <iostream> #include <cstdio> #include <cstring> #include <queue> #define INF 0x3f3f3f3f using namespace std; struct node { int u,v,f; } e[60000]; int n,m; int p[3000]; int first[3000],next[60000],ct; int g[55][55]; int a[3000]; int sum; int s,t; void add(int u, int v, int f) { e[ct].u = u; e[ct].v = v; e[ct].f = f; next[ct] = first[u]; first[u] = ct++; e[ct].u = v; e[ct].v = u; e[ct].f = 0; next[ct] = first[v]; first[v] = ct++; } int EK(int s, int t) { queue<int> q; int f=0; while(1) { memset(a,0,sizeof(a)); memset(p,-1,sizeof(p)); q.push(s); a[s]=INF; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=first[u]; i!=-1; i=next[i]) { if(!a[e[i].v]&&e[i].f) { p[e[i].v]=i; a[e[i].v]=min(a[u],e[i].f); q.push(e[i].v); } } } if(a[t]==0) break; for(int u=t; u!=s; u=e[p[u]].u) { e[p[u]].f-=a[t]; e[p[u]^1].f+=a[t]; } f+=a[t]; } return f; } void init() { sum = 0; ct = 0; memset(first,-1,sizeof(first)); memset(next,-1,sizeof(next)); for(int i=1; i<=m; i++) { for(int j=1; j<=n; j++) { scanf("%d",&g[i][j]); sum += g[i][j]; } } for(int i=1; i<=m; i++) { for(int j=1; j<=n; j++) { int tmp=(i-1)*n+j; if((i+j)%2==0) { add(s,tmp,g[i][j]); if(i>1) add(tmp,(i-2)*n+j,INF); if(i<m) add(tmp,i*n+j,INF); if(j>1) add(tmp,(i-1)*n+j-1,INF); if(j<n) add(tmp,(i-1)*n+j+1,INF); } else add(tmp,t,g[i][j]); } } } int main() { //freopen("input.txt","r",stdin); while(scanf("%d%d",&m,&n) != EOF) { s=0; t=n*m+1; init(); printf("%d\n",sum - EK(s, t)); } return 0; }
---------------------------------------------------------------------
。。。。。。。。。。。。。。。。。。。。。。。。
【网络流】hdu 1569 方格取数(2),布布扣,bubuko.com
时间: 2024-10-19 19:32:52