zoukankan      html  css  js  c++  java
  • hdu 1569 方格取数(2) 最大权独立集

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1569

    题解:
    因为这个数据比较大,所以用动态规划会超时。
    将图转换成黑白棋盘问题,i + j 为奇数的与s节点相连,边的权值为棋盘上对应位置的值,其他的与t节点相连,

    边的权值为棋盘上对应位置的值,然后让棋盘上相邻之间的节点用边相连,边的权值为INF。这样问题就转换为

    了最大点权独立集问题。
    定理:
    1、最大点权独立集 = sum - 最小点权覆盖集。
    2、最小点权覆盖集 = 最小割 = 最大流

    dinic实现:

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 2550;
    const int inf = 0x7fffffff;
    
    struct node
    {
        int v,cost;
        int next;
    }edge[8*maxn];
    int map[55][55];
    int head[maxn],dis[maxn],id;
    int source,sink,res;
    int n,m;
    void add_edge(int u,int v,int cost)
    {
        edge[id].v = v;edge[id].cost = cost;edge[id].next = head[u];head[u] = id++;
        edge[id].v = u;edge[id].cost = 0;   edge[id].next = head[v];head[v] = id++;
    }
    void build()
    {
        id = source = 0;sink = n*m+5;
        memset(head,-1,sizeof(head));
        int i,j,t;
        for( i = 1; i <= n; i++)
        {
            for( j = 1; j <= m; j++)
            {
                t = (i-1)*m+j+1;
                if((i+j)&1)
                {
                    add_edge(source,t,map[i][j]);
                    if( i > 1)
                        add_edge(t,t-m,inf);
                    if( i < n )
                        add_edge(t,t+m,inf);
                    if( j > 1)
                        add_edge(t,t-1,inf);
                    if( j < m )
                        add_edge(t,t+1,inf);
                }
                else
                    add_edge(t,sink,map[i][j]);
            }
        }
    }
    bool bfs()
    {
        memset(dis,-1,sizeof(dis));
        queue<int>que;
        dis[source] = 0;
        que.push(source);
    
        while( !que.empty())
        {
            int u = que.front();
            que.pop();
    
            for( id = head[u] ; id != -1; id = edge[id].next)
            {
                int v = edge[id].v;
                if( edge[id].cost > 0 && dis[v] == -1)
                {
                    dis[v] = dis[u] + 1;
                    que.push(v);
                }
            }
        }
        return dis[sink] != -1;
    }
    
    int dinic(int u,int flow)
    {
        if( u == sink)return flow;
        int tmp = flow;
        for(int id = head[u] ; id != -1 ; id = edge[id].next)
        {
            int v = edge[id].v;
            if( edge[id].cost > 0 && dis[v] == dis[u] + 1)
            {
                int c = dinic(v,edge[id].cost < tmp ? edge[id].cost : tmp);
                tmp -= c;
                edge[id].cost -= c;
                edge[id^1].cost += c;
                if( tmp == 0)break;
            }
        }
        return flow - tmp;
    }
    
    int get_max_flow()
    {
        int max_flow = 0;
        while( bfs() )
            max_flow += dinic(source,res);
        return max_flow;
    }
    
    
    int main()
    {
        int i,j;
        while( scanf("%d%d",&n,&m) != EOF)
        {
            res = 0;
            for( i = 1; i <= n; i++)
            for( j = 1; j <= m; j++)
            {
                scanf("%d",&map[i][j]);
                res += map[i][j];
            }
            build();
            printf("%d\n",res-get_max_flow());
        }
        return 0;
    }
    


     

  • 相关阅读:
    在 Eclipse Workbench 之外使用 Eclipse GUI
    GB2312,GBK,Unicode
    木偶一之推荐系统
    Matlab:任意矩阵计算分布密度(海明距离的分布密度)
    live555在arm linux下的交叉编译,并下载的Arm板播放H264文件
    java设计模式之原型模式
    HDU 1102
    poj3661另一种做法(滚动数组)
    基于QT的小游戏细菌病毒战
    某代码查看器的保护突破
  • 原文地址:https://www.cnblogs.com/LUO257316/p/3220803.html
Copyright © 2011-2022 走看看