hdu(1569) 最大点权独立集
2011-08-21 21:09
253 查看
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1569
题意描述:
分析:该题求一个二分图的最大权独立集,那么如何建立二分图呢? 考虑到最大权独立集和最小点权覆盖集是互补的,那么我们就可以将该问题转化为最小点权覆盖了,从而转换为最小割问题! 下面给出两种建图的方法:
第一种:根据奇偶建立二分图,如果(i+j)%2==0 那么可以是该点和源点连接,其余的和汇点连接,权值均为该点的点权,之后若i+j为偶数的点和i+j为奇数的点之间相邻,那么就连一条从为偶数的点到为奇数的点的边,权值为无穷大
第二种: 拆点,将每个点权拆为两个点u',u‘’如果两个点相邻,那么连一条边从u‘到v’‘,权值为无穷大,u’连接源点,权值为点权,u‘’连接汇点,权值也为点权
代码如下:
ps: 加注释的为第一种建图方法,未加的为第二种建图方法
题意描述:
给你一个m*n的格子的棋盘,每个格子里面有一个非负数。 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大 |
第一种:根据奇偶建立二分图,如果(i+j)%2==0 那么可以是该点和源点连接,其余的和汇点连接,权值均为该点的点权,之后若i+j为偶数的点和i+j为奇数的点之间相邻,那么就连一条从为偶数的点到为奇数的点的边,权值为无穷大
第二种: 拆点,将每个点权拆为两个点u',u‘’如果两个点相邻,那么连一条边从u‘到v’‘,权值为无穷大,u’连接源点,权值为点权,u‘’连接汇点,权值也为点权
代码如下:
ps: 加注释的为第一种建图方法,未加的为第二种建图方法
/*#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int inf = 0x3fffffff; const int N = 2600; const int E = 30000; int e,head ; int dep ,que ,cur ; struct node { int x,y; int nxt; int c; }edge[E]; void addedge(int u,int v,int c) { edge[e].x=u; edge[e].y=v; edge[e].nxt=head[u]; edge[e].c=c; head[u]=e++; edge[e].x=v; edge[e].y=u; edge[e].nxt=head[v]; edge[e].c=0; head[v]=e++; } int maxflow(int s,int t) { int i,j,k,front,rear,top,min,res=0; while(1) { memset(dep,-1,sizeof(dep)); front=0; rear=0; que[rear++]=s; dep[s]=0; while(front!=rear) { i=que[front++]; for(j=head[i];j!=-1;j=edge[j].nxt) if(edge[j].c&&dep[edge[j].y]==-1) { dep[edge[j].y]=dep[i]+1; que[rear++]=edge[j].y; } } if(dep[t]==-1) break; memcpy(cur,head,sizeof(head)); for(i=s,top=0;;) { if(i==t) { min=inf; for(k=0;k<top;k++) if(min>edge[que[k]].c) { min=edge[que[k]].c; front=k; } for(k=0;k<top;k++) { edge[que[k]].c-=min; edge[que[k]^1].c+=min; } res+=min; i=edge[que[top=front]].x; } for(j=cur[i];cur[i]!=-1;j=cur[i]=edge[cur[i]].nxt) if(dep[edge[j].y]==dep[i]+1&&edge[j].c) break; if(cur[i]!=-1) { que[top++]=cur[i]; i=edge[cur[i]].y; } else { if(top==0) break; dep[i]=-1; i=edge[que[--top]].x; } } } return res; } int main() { int n,m,i,j,c,sum; while(scanf("%d%d",&n,&m)!=EOF) { memset(head,-1,sizeof(head)); e = 0; int src = 0; int sin = n*m+1; sum = 0; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { scanf("%d",&c); sum+=c; if((i+j)%2 == 0) { addedge(src,(i-1)*m+j,c); if(i>1) addedge((i-1)*m+j,(i-2)*m+j,inf); if(j>1) addedge((i-1)*m+j,(i-1)*m+j-1,inf); if(i<n) addedge((i-1)*m+j,i*m+j,inf); if(j<m) addedge((i-1)*m+j,(i-1)*m+j+1,inf); } else addedge((i-1)*m+j,sin,c); } // cout << sum <<endl; printf("%d\n",sum-maxflow(src,sin)); } return 0; } */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N = 5100; const int E = 80000; const int inf = 0x3fffffff; int e,head ; int dep ,que ,cur ; struct node { int x,y; int nxt; int c; }edge[E]; void addedge(int u,int v,int c) { edge[e].x=u; edge[e].y=v; edge[e].nxt=head[u]; edge[e].c=c; head[u]=e++; edge[e].x=v; edge[e].y=u; edge[e].nxt=head[v]; edge[e].c=0; head[v]=e++; } int maxflow(int s,int t) { int i,j,k,front,rear,top, min,res=0; while(1) { memset(dep,-1,sizeof(dep)); front=0; rear=0; que[rear++]=s; dep[s]=0; while(front!=rear) { i=que[front++]; for(j=head[i];j!=-1;j=edge[j].nxt) if(edge[j].c&&dep[edge[j].y]==-1) { dep[edge[j].y]=dep[i]+1; que[rear++]=edge[j].y; } } if(dep[t]==-1) break; memcpy(cur,head,sizeof(head)); for(i=s,top=0;;) { if(i==t) { min=inf; for(k=0;k<top;k++) if(min>edge[que[k]].c) { min=edge[que[k]].c; front=k; } for(k=0;k<top;k++) { edge[que[k]].c-=min; edge[que[k]^1].c+=min; } res+=min; i=edge[que[top=front]].x; } for(j=cur[i];cur[i]!=-1;j=cur[i]=edge[cur[i]].nxt) if(dep[edge[j].y]==dep[i]+1&&edge[j].c) break; if(cur[i]!=-1) { que[top++]=cur[i]; i=edge[cur[i]].y; } else { if(top==0) break; dep[i]=-1; i=edge[que[--top]].x; } } } return res; } int main () { int n, m,i,j; int sum, c; while(scanf("%d%d",&n,&m)!=EOF) { sum = 0; int src = 0; int sin = 2*n*m+1; e =0; memset(head,-1,sizeof(head)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) { scanf("%d",&c); sum += c; addedge(src,(i-1)*m+j,c);//建立源点到每个点的 addedge((i-1)*m+j+n*m,sin,c); if(i>1) addedge((i-1)*m+j,(i-2)*m+n*m+j,inf); if(j>1) addedge((i-1)*m+j, (i-1)*m+j-1+n*m,inf); if(i<n) addedge((i-1)*m+j,i*m+n*m+j,inf); if(j<m) addedge((i-1)*m+j,(i-1)*m+j+n*m+1,inf); } int flow = maxflow(src,sin); printf("%d\n",sum-flow/2); } return 0; }
相关文章推荐
- hdu 1569 方格取数(2) 网络流--最大点权独立集
- hdu 1569 方格取数(2)【最大权独立集合-------最大流Edmond_Karp】
- HDU 1569 最大点权独立集
- hdu 1569 方格取数(2) 最大权独立集
- hdu 1569 方格取数——最大点权独立集
- hdu 1569 方格取数(2) 网络流 最大点权独立集
- HDU 1569 方格取数(2) 最大点权独立集
- hdu 1569 方格取数(2) 最大点权独立集
- hdu 1569 方格取数(2) 最大点权独立集
- hdu-1569(网络流)-最大点权独立集
- HDU 1569 方格取数(2)(最大独立点集)
- HDU 1569 方格取数(2) 最大点权独立集
- hdu 1569 最大点权独立集
- hdu 1569 最大点权独立集
- 独立最小【网络流第五弹】最大点权独立集 ——HDU 1569 方格取数(2)
- 【HDU 1569】 方格取数2 --最大点权独立集
- hdu 1569 方格取数 最大点权独立集(hdu 1565)
- HDU 1068 Girls and Boys(二分图最大独立点集,3级)
- HDU-1569 方格取数(2) 最小割最大流
- hdu 2768 Cat vs. Dog (最大独立)