bzoj1475 求解最大独立集

来源:互联网 发布:松江行知进修学校 编辑:程序博客网 时间:2024/06/06 04:48

上一篇文章我写了有关二分图的相关定理和公

式:http://blog.csdn.net/qq_34564984/article/details/52778763


而这道题,很显然,行+列为奇数和偶数的点是不会有边相连的,因此,可以将相邻

点建边,则此题为裸的求最大独立点权集的题


最大独立集+最小点权覆盖=总权值


最小点权覆盖=最小割=最大流


跑一遍最大流即可


附代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<climits>#include<queue>#define N 100001#define M 400001#define inf INT_MAXusing namespace std;int n,S,T,all;int map[50][50],m[50][50];int id;int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};int head[N],pos,cur[N];struct edge{int to,next,c;}e[M];void add(int a,int b,int c){e[pos].to=b,e[pos].next=head[a],e[pos].c=c,head[a]=pos;pos++;e[pos].to=a,e[pos].next=head[b],e[pos].c=0,head[b]=pos;pos++;}void init(){pos=0;memset(head,-1,sizeof(head));}queue<int>Q;bool vis[N];int d[N];bool bfs(){memset(vis,0,sizeof(vis));vis[S]=1,d[S]=0;Q.push(S);while(!Q.empty()){int u=Q.front();Q.pop();for(int i=head[u];i!=-1;i=e[i].next){int v=e[i].to;if(!vis[v]&&e[i].c>0){vis[v]=1;d[v]=d[u]+1;Q.push(v);}}}return vis[T];}int dfs(int u,int a){if(u==T||a==0)return a;int f,flow=0;for(int &i=cur[u];i!=-1;i=e[i].next){int v=e[i].to;if(d[v]==d[u]+1&&(f=dfs(v,min(a,e[i].c)))>0){a-=f;e[i].c-=f;e[i^1].c+=f;flow+=f;if(a==0)break;}}return flow;}int dinic(){int ans=0;while(bfs()){for(int i=S;i<=T;i++)cur[i]=head[i];ans+=dfs(S,inf);}return ans;}int main(){scanf("%d",&n);S=0,T=n*n+1;init();for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){scanf("%d",&map[i][j]);id++;m[i][j]=id;all+=map[i][j];}for(int u=1;u<=n;u++)for(int v=1;v<=n;v++){if((u+v)%2){add(S,m[u][v],map[u][v]);if(u>=2)add(m[u][v],m[u-1][v],inf);if(v>=2)add(m[u][v],m[u][v-1],inf);}else{add(m[u][v],T,map[u][v]);if(u>=2)add(m[u-1][v],m[u][v],inf);if(v>=2)add(m[u][v-1],m[u][v],inf);}}printf("%d\n",all-dinic());}

3 0
原创粉丝点击