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

来源:互联网 发布:外交官 新秀丽 知乎 编辑:程序博客网 时间:2024/06/03 16:21

题目链接: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这题一样,数据变大了而已。。。

 

0 0
原创粉丝点击