zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",sum-Dinic(0,n*m+1));
        }
        return 0;
    }
  • 相关阅读:
    正在找工作/打算找工作的看过来!
    xx星空面试题
    买的书不少,看的书不多,这是病
    公司那么多 我想去面面
    Android设备直接运行java项目?还杀不死?
    node-sass安装失败 解决办法(linux和window)
    Vue + element控制鼠标右键菜单
    Vue.js中Promise、异步、同步、定时器
    选择器&伪类选择器
    根据城市名称获取对应的省份名称
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5547183.html
Copyright © 2011-2022 走看看