zoukankan      html  css  js  c++  java
  • 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外键和表关系
    列类型-字符类型
    列类型-日期时间型
    列类型
    破解MySQL的root密码
    数据库简单使用
    数据库简介
    socketserver
    python网络编程-粘包问题的解决
    python-网络编程,简单模型
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6698631.html
Copyright © 2011-2022 走看看