• HDU 1565 方格取数(1)(最大点权独立集)


    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 }
  • 相关阅读:
    mysql复制那点事
    全排列问题
    56. Merge Interval
    2. Add Two Numbers
    20. Valid Parentheses
    121. Best Time to Buy and Sell Stock
    120. Triangle
    96. Unique Binary Search Trees
    91. Decode Ways
    72. Edit Distance
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6698631.html
Copyright © 2020-2023  润新知