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

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

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

覆盖集、独立集是图论中的相关概念.

相关概念:http://blog.csdn.net/lin375691011/article/details/18908423

而这两个概念在二分图中不是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;
}
时间: 2024-10-17 14:46:31

hdu 1565&hdu 1569(网络流--最小点权值覆盖)的相关文章

HDU 1565 &amp;&amp; HDU 1569 方格取数 (网络流之最小割)

题目地址:HDU 1565       HDU 1569 刚开始接触最小割,就已经感受到了最小割的博大精深... 这建图思路倒是好想..因为好多这种关于不相邻的这种网络流都是基本都是这样建图.但是感觉毫无道理可言...看了题解后才明白这样做的意义. 下面是题解中的说法. 大概是这样分析的,题义是要我们求在一个方格内取出N个点,使得这N个独立的(不相邻)点集的和最大.我们可以将问题转化为最小割来求解.首先,我们将方格进行黑白相间的染色,然后再将任意一种颜色(黑色)作为源点,一种颜色(白色)作为汇点

HDU 4289 Control (网络流-最小割)

Control Problem Description You, the head of Department of Security, recently received a top-secret information that a group of terrorists is planning to transport some WMD 1 from one city (the source) to another one (the destination). You know their

HDU 3488--Tour【最小费用最大流 &amp;&amp; 有向环最小权值覆盖 &amp;&amp; 经典】

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 2308    Accepted Submission(s): 1156 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 3000

HDU 1863:畅通工程(带权值的并查集)

畅通工程 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 16075    Accepted Submission(s): 6677 Problem Description 省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).经过调查评估,得到的统计表中列出

HDU 1863:畅通project(带权值的并查集)

畅通project Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 16075    Accepted Submission(s): 6677 Problem Description 省政府"畅通project"的目标是使全省不论什么两个村庄间都能够实现公路交通(但不一定有直接的公路相连,仅仅要能间接通过公路可达就可以).经过

HDU 6141 I am your Father!(最小树形图+权值编码)

http://acm.hdu.edu.cn/showproblem.php?pid=6141 题意: 求最大树形图. 思路: 把边的权值变为负值,那么这就是个最小树形图了,直接套模板就可以解决. 有个问题就是n结点的父亲结点的编号要尽量小,这里有个技巧可以用,权值编码,将所有边的权值都放大1000倍,对于和n相连的边,每条边在减去(n-u)的权值.这样就会去优先考虑编号小的边,而且因为权值最大为100,所以扩大1000是不会影响结果的. 1 #include<iostream> 2 #incl

朱、刘算法:求最小树形图权值个人理解+个人详解【最小树形图模板】

什么是最小树形图?相信大家如果会过来看这篇文章,想必也应该对最小生成树有所了解的,最小生成树求的是无向图的一颗生成树的最小权值.我们的最小树形图就是来解决一个有向图的一颗生成树的最小权值,对于度娘来说,最小树形图是这样定义的:最小树形图,就是给有向带权图中指定一个特殊的点root,求一棵以root为根的有向生成树T,并且T中所有边的总权值最小. 通解最小树形图的一种算法是是1965年朱永津和刘振宏提出的复杂度为O(VE)的算法:朱.刘算法. 今天我们就来浅谈一下最小树形图的问题. 大题上完整的朱

HDU 1853--Cyclic Tour【最小费用最大流 &amp;&amp; 有向环最小权值覆盖 】

Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1950    Accepted Submission(s): 984 Problem Description There are N cities in our country, and M one-way roads connecting them. Now L

find the most comfortable road(并差集,找差值最小的权值)

find the most comfortable road Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5359    Accepted Submission(s): 2327 Problem Description XX 星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超