HDU 1569 方格取数(2) << 最大点权独立集

题意

升级版的方格取数

思路

图中选一个点就不能选四周的点,转化为二分图,求最大点权独立集。要求最大点权独立集,即是求最小点权覆盖,求点权和减去最小割,即是求最小割,即是求最大流,关于建图,每个点向周围四个点建边即可,证明与说明略。

代码

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1e4+7;
  4 const int INF=0x3f3f3f3f;
  5 struct Edge{
  6     int from,to,cap,flow;
  7 };
  8 struct DINIC{
  9     int n,m,s,t;
 10     vector<Edge> edges;
 11     vector<int> G[maxn];
 12     bool vis[maxn];
 13     int d[maxn];
 14     int cur[maxn];
 15 
 16     void AddEdge(int from,int to,int cap,int c=0)//有向图c为0
 17     {
 18         edges.push_back(Edge {from,to,cap,0});
 19         edges.push_back(Edge {to,from,c,0});
 20         m=edges.size();
 21         G[from].push_back(m-2);
 22         G[to].push_back(m-1);
 23     }
 24 
 25     bool BFS()
 26     {
 27         memset(vis,0,sizeof(vis));
 28         queue<int> Q;
 29         Q.push(s);
 30         d[s]=0;
 31         vis[s]=1;
 32         while(!Q.empty())
 33         {
 34             int x=Q.front();Q.pop();
 35             for(int i=0;i<G[x].size();i++)
 36             {
 37                 Edge& e=edges[G[x][i]];
 38                 if(!vis[e.to]&&e.cap>e.flow)
 39                 {
 40                     vis[e.to]=1;
 41                     d[e.to]=d[x]+1;
 42                     Q.push(e.to);
 43                 }
 44             }
 45         }
 46         return vis[t];
 47     }
 48 
 49     int DFS(int x,int a)
 50     {
 51         if(x==t||a==0) return a;
 52         int flow=0,f;
 53         for(int& i=cur[x];i<G[x].size();i++)
 54         {
 55             Edge& e=edges[G[x][i]];
 56             if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0)
 57             {
 58                 e.flow+=f;
 59                 edges[G[x][i]^1].flow-=f;
 60                 flow+=f;
 61                 a-=f;
 62                 if(a==0) break;
 63             }
 64         }
 65         return flow;
 66     }
 67     int Maxflow(int s,int t)
 68     {
 69         this->s=s;this->t=t;
 70         int flow=0;
 71         while(BFS())
 72         {
 73             memset(cur,0,sizeof(cur));
 74             flow+=DFS(s,INF);
 75         }
 76         return flow;
 77     }
 78 };
 79 
 80 int maze[55][55];
 81 int main()
 82 {
 83     //freopen("data.in","r",stdin);
 84     //freopen("data.out","w",stdout);
 85     int n,m;
 86     while(~scanf("%d%d",&n,&m))
 87     {
 88         int s=n*m+10,t=n*m+20;
 89         int tot=0;
 90         DINIC F;
 91         for(int i=0;i<n;i++)
 92         {
 93             for(int j=0;j<m;j++)
 94             {
 95                 scanf("%d",&maze[i][j]);
 96                 tot+=maze[i][j];
 97                 if((i+j)%2==0)
 98                 {
 99                     if(j<m-1) F.AddEdge(i*m+j,i*m+j+1,INF);
100                     if(i<n-1) F.AddEdge(i*m+j,i*m+m+j,INF);
101                     if(i>0) F.AddEdge(i*m+j,i*m-m+j,INF);
102                     if(j>0) F.AddEdge(i*m+j,i*m+j-1,INF);
103                     F.AddEdge(s,i*m+j,maze[i][j]);
104                 }
105                 else F.AddEdge(i*m+j,t,maze[i][j]);
106             }
107         }
108         int ans=tot-F.Maxflow(s,t);
109         printf("%d\n",ans);
110     }
111 }

 

posted @ 2018-12-09 13:53  computer_luo  阅读(131)  评论(0编辑  收藏  举报