• hdu 1565+hdu 1569(最大点权独立集)


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

    http://acm.hdu.edu.cn/showproblem.php?pid=1569

    先理理概念:

    点覆盖集:无向图G的一个点集,使得该图中所有边都至少有一个端点在该集合内。

    最小点权覆盖集:在带点权无向图G中,点权之和最小的覆盖集。

    点独立集:无向图G的一个点集,使得任两个在该集合中的点在原图中都不相邻。
    最大点权独立集:在带权无向图G中,点权之和最大的独立集。
    定理:
    1. 最小点权覆盖集=最小割=最大流
    2. 最大点权独立集=总权-最小点权覆盖集

    思路:

    1. 先染色,取一个点染白色,和它相邻的点染黑色
    2. 每个白点向它相邻的黑点连一条边,容量为 inf (无穷大)
    3. 增加源点S,向每一个白色点连一条边,容量为白点的权
    4. 增加汇点T,每个黑点向T连一条边,容量为黑点的权

    附上链接:http://hi.baidu.com/lerroy312/item/28111de2afe9152b6cabb853

     建图的时候要小心。

    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 using namespace std;
      5 #define MAXN 555
      6 #define MAXM 222222
      7 #define inf 1<<30
      8 
      9 struct Edge{
     10     int v,cap,next;
     11 }edge[MAXM];
     12 
     13 int head[MAXN];
     14 int pre[MAXN];
     15 int cur[MAXN];
     16 int level[MAXN];
     17 int gap[MAXN];
     18 int NE,NV,n,vs,vt;
     19 int dir[4][2]={{0,-1},{0,1},{-1,0},{1,0}};
     20 int map[22][22];
     21 bool mark[22][22];
     22 
     23 void Insert(int u,int v,int cap,int cc=0){
     24     edge[NE].v=v;edge[NE].cap=cap;
     25     edge[NE].next=head[u];head[u]=NE++;
     26 
     27     edge[NE].v=u;edge[NE].cap=cc;
     28     edge[NE].next=head[v];head[v]=NE++;
     29 }
     30 
     31 int SAP(int vs,int vt){
     32     memset(pre,-1,sizeof(pre));
     33     memset(level,0,sizeof(level));
     34     memset(gap,0,sizeof(gap));
     35     for(int i=0;i<NV;i++)cur[i]=head[i];
     36     int u=pre[vs]=vs,maxflow=0,aug=-1;
     37     gap[0]=NV;
     38     while(level[vs]<NV){
     39 loop:
     40         for(int &i=cur[u];i!=-1;i=edge[i].next){
     41             int v=edge[i].v;
     42             if(edge[i].cap&&level[u]==level[v]+1){
     43                 aug==-1?aug=edge[i].cap:aug=min(aug,edge[i].cap);
     44                 pre[v]=u;
     45                 u=v;
     46                 if(v==vt){
     47                     maxflow+=aug;
     48                     for(u=pre[u];v!=vs;v=u,u=pre[u]){
     49                         edge[cur[u]].cap-=aug;
     50                         edge[cur[u]^1].cap+=aug;
     51                     }
     52                     aug=-1;
     53                 }
     54                 goto loop;
     55             }
     56         }
     57         int minlevel=NV;
     58         for(int i=head[u];i!=-1;i=edge[i].next){
     59             int v=edge[i].v;
     60             if(edge[i].cap&&minlevel>level[v]){
     61                 cur[u]=i;
     62                 minlevel=level[v];
     63             }
     64         }
     65         gap[level[u]]--;
     66         if(gap[level[u]]==0)break;
     67         level[u]=minlevel+1;
     68         gap[level[u]]++;
     69         u=pre[u];
     70     }
     71     return maxflow;
     72 }
     73 
     74 int main(){
     75     while(~scanf("%d",&n)){
     76         vs=0,vt=n*n+1,NE=0,NV=n*n+2;
     77         int sum=0;
     78         memset(head,-1,sizeof(head));
     79         memset(mark,false,sizeof(mark));
     80         for(int i=1;i<=n;i++){
     81             for(int j=1;j<=n;j++){
     82                 scanf("%d",&map[i][j]);
     83                 sum+=map[i][j];
     84             }
     85         }
     86         for(int i=1;i<=n;i++){
     87             for(int j=1;j<=n;j++){
     88                 if(!mark[i][j]){
     89                     Insert(vs,(i-1)*n+j,map[i][j]);
     90                     for(int k=0;k<4;k++){
     91                         int x=i+dir[k][0];
     92                         int y=j+dir[k][1];
     93                         if(x>=1&&x<=n&&y>=1&&y<=n){
     94                             Insert((i-1)*n+j,(x-1)*n+y,inf);
     95                             //建图的时候要小心,每个点只能连一次
     96                             if(!mark[x][y])Insert((x-1)*n+y,vt,map[x][y]);
     97                             mark[x][y]=true;
     98                         }
     99                     }
    100                 }
    101             }
    102         }
    103         printf("%d\n",sum-SAP(vs,vt));
    104     }
    105     return 0;
    106 }

     ps:hdu 1569这题一样,数据变大了而已。。。

  • 相关阅读:
    Shell学习笔记之shell脚本和python脚本实现批量ping IP测试
    SNMP学习笔记之SNMPv3的配置和认证以及TroubleShooting
    Web负载均衡学习笔记之四层和七层负载均衡的区别
    SNMP学习笔记之SNMP树形结构介绍
    Web负载均衡学习笔记之实现负载均衡的几种实现方式
    HCNP学习笔记之子网掩码的计算和划分详细
    HCNP学习笔记之IP地址、子网掩码、网关的关系
    Linux学习笔记之passwd:Authentication token manipulation error_错误的解决办法
    ubuntu 系统关键指令
    Jetson tk1 hash sum mismatch
  • 原文地址:https://www.cnblogs.com/wally/p/3061465.html
Copyright © 2020-2023  润新知