您的位置:首页 > 理论基础 > 计算机网络

hdu-1569(网络流)-最大点权独立集

2012-06-05 21:52 387 查看
最大点权独立集=总权值-最小点权覆盖集

最大点权独立集=最大流

最小点权覆盖集=最小割

根据奇偶建立二分图,

if(i+j)%2==0 源点和该点连接,权值为该点的点权,

if(i+j)%2==1 该点和汇点连接,权值为该点的点权,

之后若i+j为偶数的点和i+j为奇数的点之间相邻,那么就连一条从为偶数的点到为奇数的点的边,权值为无穷大

View Code

/*
Problem : 1569-方格取数(2)      Judge Status : Accepted
RunId : 6039695    Language : G++    Author : 2010201211
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
#define E 30000
#define V 2600
#define inf 0x3f3f3f3f
struct Edge
{
int u,v,c,next;
}edge[E];
int n,m,cnt;
int dist[V];
int head[V];
int que[V];
int sta[V];

int film[25][10];
int week,sum,s,t;

void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c){
edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c;
edge[cnt].next=head[u];head[u]=cnt++;

edge[cnt].u=v;edge[cnt].v=u;edge[cnt].c=0;
edge[cnt].next=head[v];head[v]=cnt++;
}

int dinic(int s,int t){
int ans=0;
while(true){
int left,right,u,v;

memset(dist,-1,sizeof(dist));
left=right=0;
que[right++]=s;
dist[s]=0;

while(left<right){//bfs构造层次网络
u=que[left++];
for(int k=head[u];k!=-1;k=edge[k].next){
u=edge[k].u;
v=edge[k].v;
if(edge[k].c>0 && dist[v]==-1){
dist[v]=dist[u]+1;
que[right++]=v;
/*if(v==t){
left=right;
break;
}*/
}
}
}

if(dist[t]==-1) break;//汇点不在层次网络中,算法结束.

int top=0;
int now=s;

while(true){//层次图中进行一次dfs增广
if(now!=t){//dfs未到汇点
int k;
for(k=head[now];k!=-1;k=edge[k].next){//判断now之后是否有可用点(入度是否为0)
if(edge[k].c>0 && dist[edge[k].u]+1==dist[edge[k].v]) break;
}
if(k!=-1){//如果now之后有可用点(入度>0)
//cout << top << endl;
sta[top++]=k;//边入栈
now=edge[k].v;
}
else{//now之后没有可用点
if(top==0) break;
dist[edge[sta[--top]].v]=-1;//从p和层次图中删除点u以及u连接的所有边
now=edge[sta[top]].u;
}

}
else{//dfs到汇点
int flow=inf,ebreak;
//(1)增广p
for(int i=0;i<top;i++){
if(flow>edge[sta[i]].c){
flow=edge[sta[i]].c;
ebreak=i;
}
}
ans+=flow;
for(int i=0;i<top;i++){
edge[sta[i]].c-=flow;//正向边减流
edge[sta[i]^1].c+=flow;//反向边加流
}
//(2)退至p中从源点可到达的最后一个顶点
now=edge[sta[ebreak]].u;
top=ebreak;
}
}

}
return ans;
}
int main(){
int n,m,i,j,c,sum;
while(scanf("%d%d",&n,&m)!=EOF){
init();
int src=0;
int end=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,end,c);
}
int res=dinic(src,end);
printf("%d\n",sum-res);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: