hdu 1565&hdu 1569(网络流--最小点权值覆盖)

Posted AC菜鸟机

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 1565&hdu 1569(网络流--最小点权值覆盖)相关的知识,希望对你有一定的参考价值。

方格取数(1)

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7717    Accepted Submission(s): 2911


Problem Description
给你一个n*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
 

 

Input
包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20)
 

 

Output
对于每个测试实例,输出可能取得的最大的和
 

 

Sample Input
3 75 15 21 75 15 28 34 70 5
 

 

Sample Output
188
 

 

Author
ailyanlu
 
最小点权覆盖集+最大点权独立集 = 图的总权值
最小点权覆盖集=最大流=最小割
覆盖集、独立集是图论中的相关概念.
而这两个概念在二分图中不是NP问题,所以要把这个图转化为二分图求解。
先建立一个超级源点和一个超级汇点,然后将(x+y)为偶数(或者奇数)的点与超级源点连接,将(x+y)为奇数(或者偶数)的点与超级汇点连接,二分图两边的点相连的权值都记为正无穷,然后对此图求最小割。然后 最大点权独立集 = 总权值 - 最小点权覆盖集
#include <iostream>
#include <queue>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int N = 405;
const int INF = 999999999;
struct Edge{
    int v,w,next;
}edge[N*N];
int head[N];
int level[N];
int mp[N][N];
int n;
void addEdge(int u,int v,int w,int &k){
    edge[k].v = v,edge[k].w=w,edge[k].next=head[u],head[u]=k++;
    edge[k].v = u,edge[k].w=0,edge[k].next=head[v],head[v]=k++;
}
int BFS(int src,int des){
    queue<int >q;
    memset(level,0,sizeof(level));
    level[src]=1;
    q.push(src);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        if(u==des) return 1;
        for(int k = head[u];k!=-1;k=edge[k].next){
            int v = edge[k].v,w=edge[k].w;
            if(level[v]==0&&w!=0){
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
    return -1;
}
int dfs(int u,int des,int increaseRoad){
    if(u==des) return increaseRoad;
    int ret=0;
    for(int k=head[u];k!=-1;k=edge[k].next){
        int v = edge[k].v,w=edge[k].w;
        if(level[v]==level[u]+1&&w!=0){
            int MIN = min(increaseRoad-ret,w);
            w = dfs(v,des,MIN);
            edge[k].w -=w;
            edge[k^1].w+=w;
            ret+=w;
            if(ret==increaseRoad) return ret;
        }
    }
    return ret;
}
int Dinic(int src,int des){
    int ans = 0;
    while(BFS(src,des)!=-1) ans+=dfs(src,des,INF);
    return ans;
}
int P(int x,int y){
    return (x-1)*n+y;
}
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(head,-1,sizeof(head));
        int tot = 0;
        int src = 0,des = n*n+1;
        int sum = 0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&mp[i][j]);
                sum+=mp[i][j];
                if((i+j)%2==0){
                    addEdge(src,P(i,j),mp[i][j],tot);
                }else{
                    addEdge(P(i,j),des,mp[i][j],tot);
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                for(int k=0;k<=3;k++){
                    int x = i+dir[k][0];
                    int y = j+dir[k][1];
                    if(x<1||x>n||y<1||y>n) continue;
                    if((i+j)%2==0){
                        addEdge(P(i,j),P(x,y),INF,tot);
                    }
                }
            }
        }
        printf("%d\n",sum-Dinic(0,n*n+1));
    }
    return 0;
}

 hdu 1569

#include <iostream>
#include <queue>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int N = 2600;
const int INF = 999999999;
struct Edge{
    int v,w,next;
}edge[N*N];
int head[N];
int level[N];
int mp[55][55];
int n,m;
void addEdge(int u,int v,int w,int &k){
    edge[k].v = v,edge[k].w=w,edge[k].next=head[u],head[u]=k++;
    edge[k].v = u,edge[k].w=0,edge[k].next=head[v],head[v]=k++;
}
int BFS(int src,int des){
    queue<int >q;
    memset(level,0,sizeof(level));
    level[src]=1;
    q.push(src);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        if(u==des) return 1;
        for(int k = head[u];k!=-1;k=edge[k].next){
            int v = edge[k].v,w=edge[k].w;
            if(level[v]==0&&w!=0){
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
    return -1;
}
int dfs(int u,int des,int increaseRoad){
    if(u==des) return increaseRoad;
    int ret=0;
    for(int k=head[u];k!=-1;k=edge[k].next){
        int v = edge[k].v,w=edge[k].w;
        if(level[v]==level[u]+1&&w!=0){
            int MIN = min(increaseRoad-ret,w);
            w = dfs(v,des,MIN);
            edge[k].w -=w;
            edge[k^1].w+=w;
            ret+=w;
            if(ret==increaseRoad) return ret;
        }
    }
    return ret;
}
int Dinic(int src,int des){
    int ans = 0;
    while(BFS(src,des)!=-1) ans+=dfs(src,des,INF);
    return ans;
}
int P(int x,int y){
    return (x-1)*m+y;
}
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(head,-1,sizeof(head));
        int tot = 0;
        int src = 0,des = n*m+1;
        int sum = 0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&mp[i][j]);
                sum+=mp[i][j];
                if((i+j)%2==0){
                    addEdge(src,P(i,j),mp[i][j],tot);
                }else{
                    addEdge(P(i,j),des,mp[i][j],tot);
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                for(int k=0;k<=3;k++){
                    int x = i+dir[k][0];
                    int y = j+dir[k][1];
                    if(x<1||x>n||y<1||y>m) continue;
                    if((i+j)%2==0){
                        addEdge(P(i,j),P(x,y),INF,tot);
                    }
                }
            }
        }
        printf("%d\n",sum-Dinic(0,n*m+1));
    }
    return 0;
}

 

以上是关于hdu 1565&hdu 1569(网络流--最小点权值覆盖)的主要内容,如果未能解决你的问题,请参考以下文章

hdu 1569 &1565 (二分图带权最大独立集 - 最小割应用)

HDU 1565 1569 方格取数(最大点权独立集)

HDU 1565 - 方格取数 - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]

hdu1569-方格取数-二分图网络流

hdu 1569 方格取数 (网络流)

HDU1569 最大流(最大点权独立集)