zoukankan      html  css  js  c++  java
  • hdu 3657(最大点权独立集)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3657

    思路我就不详细讲了,这位大牛讲的很清楚:http://blog.csdn.net/cold__v__moon/article/details/7924269

    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #define MAXN 55
      5 #define MAXM 55*55
      6 #define inf 1<<30
      7 using namespace std;
      8  struct Edge{
      9      int v,cap,next;
     10  }edge[MAXM*11];
     11 
     12 int map[MAXN][MAXN];
     13 int head[MAXM];
     14 int pre[MAXM];
     15 int cur[MAXM];
     16 int level[MAXM];
     17 int gap[MAXM];
     18 int vs,vt,NV,n,m,k,NE;
     19 bool mark[MAXN][MAXN];
     20 int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
     21 
     22  
     23  void Insert(int u,int v,int cap,int cc=0){
     24      edge[NE].cap=cap;edge[NE].v=v;
     25      edge[NE].next=head[u];head[u]=NE++;
     26  
     27      edge[NE].cap=cc;edge[NE].v=u;
     28      edge[NE].next=head[v];head[v]=NE++;
     29  }
     30  
     31  
     32  //参数,源点,汇点
     33  int SAP(int vs,int vt){
     34      memset(level,0,sizeof(level));
     35      memset(pre,-1,sizeof(pre));
     36      memset(gap,0,sizeof(gap));
     37      //cur[i]保存的是当前弧
     38      for(int i=0;i<=NV;i++)cur[i]=head[i];
     39      int u=pre[vs]=vs;//源点的pre还是其本身
     40      int maxflow=0,aug=-1;
     41      gap[0]=NV;
     42      while(level[vs]<NV){
     43  loop :
     44          for(int &i=cur[u];i!=-1;i=edge[i].next){
     45              int v=edge[i].v;//v是u的后继
     46              //寻找可行弧
     47              if(edge[i].cap&&level[u]==level[v]+1){
     48                  //aug表示增广路的可改进量
     49                  aug==-1?(aug=edge[i].cap):(aug=min(aug,edge[i].cap));
     50                  pre[v]=u;
     51                  u=v;
     52                  //如果找到一条增广路
     53                  if(v==vt){
     54                      maxflow+=aug;//更新最大流;
     55                      //路径回溯更新残留网络
     56                      for(u=pre[v];v!=vs;v=u,u=pre[u]){
     57                          //前向弧容量减少,反向弧容量增加
     58                          edge[cur[u]].cap-=aug;
     59                          edge[cur[u]^1].cap+=aug;
     60                      }
     61                      aug=-1;
     62                  }
     63                  goto loop;
     64              }
     65          }
     66          int minlevel=NV;
     67          //寻找与当前点相连接的点中最小的距离标号(重标号)
     68          for(int i=head[u];i!=-1;i=edge[i].next){
     69              int v=edge[i].v;
     70              if(edge[i].cap&&minlevel>level[v]){
     71                  cur[u]=i;//保存弧
     72                  minlevel=level[v];
     73              }
     74          }
     75          if((--gap[level[u]])==0)break;//更新gap数组后如果出现断层,则直接退出。
     76          level[u]=minlevel+1;//重标号
     77          gap[level[u]]++;//距离标号为level[u]的点的个数+1;
     78          u=pre[u];//转当前点的前驱节点继续寻找可行弧
     79      }
     80      return maxflow;
     81  } 
     82 
     83 
     84 int main(){
     85     int u,v,sum;
     86     while(~scanf("%d%d%d",&n,&m,&k)){
     87         vs=0,vt=n*m+1,NV=vt+1,sum=0,NE=0;
     88         memset(mark,false,sizeof(mark));
     89         memset(head,-1,sizeof(head));
     90         for(int i=1;i<=n;i++){
     91             for(int j=1;j<=m;j++){
     92                 scanf("%d",&map[i][j]);
     93                 sum+=map[i][j];
     94             }
     95         }
     96         
     97         for(int i=1;i<=k;i++){
     98             scanf("%d%d",&u,&v);
     99             mark[u][v]=true;
    100         }
    101         for(int i=1;i<=n;i++){
    102             for(int j=1;j<=m;j++){
    103                 if((i+j)%2==1){
    104                     mark[i][j]?Insert(vs,(i-1)*m+j,inf):Insert(vs,(i-1)*m+j,map[i][j]);
    105                     for(int l=0;l<4;l++){
    106                         int xx=i+dir[l][0],yy=j+dir[l][1];
    107                         if(xx>=1&&xx<=n&&yy>=1&&yy<=m){
    108                             Insert((i-1)*m+j,(xx-1)*m+yy,(map[i][j]&map[xx][yy])*2);
    109                         }
    110                     }
    111                 }else{
    112                     mark[i][j]?Insert((i-1)*m+j,vt,inf):Insert((i-1)*m+j,vt,map[i][j]);
    113                 }
    114             }
    115         }
    116         printf("%d\n",sum-SAP(vs,vt));
    117     }
    118     return 0;
    119 }
    120 
    121 
    122                     
  • 相关阅读:
    FMDB使用的一点心得:数据库创建、制表、查询等以及image转换成二进制nsdata保存到数据库中
    Java基本数据类型
    hashtable C++实现
    Libgdx中TextButton的一些思考
    [伯努利数] poj 1707 Sum of powers
    POJ 3020:Antenna Placement(无向二分图的最小路径覆盖)
    flume 读取kafka 数据
    [R] 之 帮助函数
    [python] 之 类编码细节
    [python] 之 装饰器
  • 原文地址:https://www.cnblogs.com/wally/p/3065127.html
Copyright © 2011-2022 走看看