HDU1569+最大点权集
1 /* 2 最大点权独立集=总权值-最小点权覆盖集 3 最大点权独立集=最大流 4 最小点权覆盖集=最小割 5 6 题意: 7 给你一个m*n的格子的棋盘,每个格子里面有一个非负数。 8 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。 9 根据奇偶建立二分图, 10 if(i+j)%2==0 源点和该点连接,权值为该点的点权, 11 if(i+j)%2==1 该点和汇点连接,权值为该点的点权, 12 之后若i+j为偶数的点和i+j为奇数的点之间相邻,那么就连一条从为偶数的点到为奇数的点的边,权值为无穷大 13 */ 14 #include<stdio.h> 15 #include<string.h> 16 #include<stdlib.h> 17 #include<algorithm> 18 #include<iostream> 19 #include<math.h> 20 using namespace std; 21 const int inf = 0x3f3f3f3f; 22 const int maxn = 2605; 23 const int maxm = 30005; 24 const int dx[]={1,-1,0,0}; 25 const int dy[]={0,0,1,-1}; 26 struct Node{ 27 int u,v,next,val; 28 }edge[ maxm ]; 29 int head[ maxn ],cnt; 30 void init(){ 31 cnt = 0; 32 memset( head,-1,sizeof( head ) ); 33 } 34 void addedge( int a,int b,int c ){ 35 edge[ cnt ].u = a; 36 edge[ cnt ].v = b; 37 edge[ cnt ].val = c; 38 edge[ cnt ].next = head[ a ]; 39 head[ a ] = cnt++; 40 41 edge[ cnt ].u = b; 42 edge[ cnt ].v = a; 43 edge[ cnt ].val = 0; 44 edge[ cnt ].next = head[ b ]; 45 head[ b ] = cnt++; 46 } 47 48 int queue[ maxn ]; 49 int lev[ maxn ]; 50 int Dinic( int start,int end ){ 51 int max_flow = 0; 52 while( true ){ 53 int Head,Tail,id; 54 Head = Tail = 0; 55 queue[ Tail++ ] = start; 56 memset( lev,-1,sizeof( lev ) ); 57 lev[ start ] = 0; 58 while( Head<Tail ){ 59 id = head[ queue[ Head++ ] ]; 60 while( id!=-1 ){ 61 if( edge[ id ].val>0&&lev[edge[id].v]==-1 ){ 62 lev[edge[id].v] = lev[edge[id].u]+1; 63 queue[Tail++] = edge[id].v; 64 if( edge[id].v==end ){ 65 Head = Tail; 66 break;//分层完成 67 } 68 } 69 id = edge[id].next; 70 } 71 }//bfs构造层次网络 72 73 if( lev[end]==-1 ) break; 74 75 id = start; 76 Tail = 0; 77 //这里queue被当作stack来用 78 while( true ){//层次网络中进行dfs 79 if( id==end ){//dfs找到汇点 80 int flow = inf; 81 int flag = -1; 82 for( int i=0;i<Tail;i++ ){ 83 if( edge[queue[i]].val<flow ){ 84 flow = edge[queue[i]].val; 85 flag = i; 86 } 87 }//寻找最小的边 88 for( int i=0;i<Tail;i++ ){ 89 edge[ queue[i] ].val -= flow; 90 edge[ queue[i]^1 ].val += flow; 91 } 92 if( flag!=-1 ) 93 { 94 max_flow += flow; 95 Tail = flag; 96 id = edge[ queue[flag] ].u; 97 } 98 else 99 return inf; 100 } 101 id = head[ id ]; 102 while( id!=-1 ){ 103 if( edge[id].val>0&&(lev[edge[id].u]+1==lev[edge[id].v]) ){ 104 break; 105 } 106 id = edge[id].next; 107 } 108 if( id!=-1 ){ 109 queue[Tail++] = id; 110 id = edge[id].v; 111 } 112 else{ 113 if( Tail==0 ) break; 114 lev[ edge[queue[Tail-1]].v ] = -1; 115 id = edge[queue[--Tail]].u; 116 } 117 } 118 } 119 return max_flow; 120 } 121 int main(){ 122 int m,n; 123 while( scanf("%d%d",&n,&m)!=EOF ){ 124 init(); 125 int sum = 0; 126 int temp; 127 for( int i=1;i<=n;i++ ){ 128 for( int j=1;j<=m;j++ ){ 129 scanf("%d",&temp); 130 if( (i+j)%2==0 ){ 131 addedge( 0,(i-1)*m+j,temp ); 132 } 133 else{ 134 addedge( (i-1)*m+j,n*m+1,temp ); 135 } 136 sum += temp; 137 } 138 } 139 for( int i=1;i<=n;i++ ){ 140 for( int j=1;j<=m;j++ ){ 141 if( (i+j)%2==0 ){ 142 for( int k=0;k<4;k++ ){ 143 int tx = i+dx[k]; 144 int ty = j+dy[k]; 145 if( tx>=1&&tx<=n&&ty>=1&&ty<=m ){ 146 addedge( (i-1)*m+j,(tx-1)*m+ty,inf ); 147 } 148 } 149 } 150 } 151 } 152 int start = 0; 153 int end = n*m+1; 154 int ans = Dinic( start,end ); 155 //printf("sum = %d,ans = %d\n",sum,ans); 156 printf("%d\n",sum-ans); 157 } 158 return 0; 159 }
keep moving...