• hdu1565+hdu1569(最大点权独立集)


    传送门:hdu1565 方格取数(1)

    传送门:hdu1569 方格取数(2)

    定理:
    1. 最小点权覆盖集=最小割=最大流
    2. 最大点权独立集=总权-最小点权覆盖集

    步骤:

    1. 先染色,取一个点染白色,和它相邻的点染黑色
    2. 每个白点向它相邻的黑点连一条边,容量为 inf (无穷大)
    3. 增加源点S,向每一个白色点连一条边,容量为白点的权
    4. 增加汇点T,每个黑点向T连一条边,容量为黑点的权

    #pragma comment(linker,"/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <limits.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstdlib>
    #include <stack>
    #include <vector>
    #include <set>
    #include <map>
    #define LL long long
    #define mod 100000000
    #define inf 0x3f3f3f3f
    #define eps 1e-6
    #define N 2510
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define PII pair<int,int>
    using namespace std;
    inline int read()
    {
        char ch=getchar();
        int x=0,f=1;
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,m,vs,vt,tot,NV;
    int head[N],gap[N],level[N],q[N];
    struct edge
    {
        int v,w,next;
        edge(){}
        edge(int v,int w,int next):v(v),w(w),next(next){}
    }e[N*N];
    void addedge(int u,int v,int w)
    {
        e[tot]=edge(v,w,head[u]);
        head[u]=tot++;
        e[tot]=edge(u,0,head[v]);
        head[v]=tot++;
    }
    void init()
    {
        memset(head,-1,sizeof(head));
        tot=0;
    }
    /***************************SAP***********************/
    void bfs(int vt)
    {
        memset(level,-1,sizeof(level));
        memset(gap,0,sizeof(gap));
        level[vt]=0;
        gap[level[vt]]++;
        queue<int>que;
        que.push(vt);
        while(!que.empty()) {
            int u=que.front();
            que.pop();
            for(int i=head[u]; i!=-1; i=e[i].next) {
                int v=e[i].v;
                if(level[v]!=-1)continue;
                level[v]=level[u]+1;
                gap[level[v]]++;
                que.push(v);
    
            }
        }
    }
    int pre[N];
    int cur[N];
    int SAP()
    {
        bfs(vt);
        memset(pre,-1,sizeof(pre));
        memcpy(cur,head,sizeof(head));
        int u=pre[vs]=vs,flow=0,aug=inf;
        gap[0]=NV;
        while(level[vs]<NV) {
            bool flag=false;
            for(int &i=cur[u]; i!=-1; i=e[i].next) {
                int v=e[i].v;
                if(e[i].w&&level[u]==level[v]+1) {
                    flag=true;
                    pre[v]=u;
                    u=v;
                    aug=min(aug,e[i].w);
                    if(v==vt) {
                        flow+=aug;
                        for(u=pre[v]; v!=vs; v=u,u=pre[u]) {
                            e[cur[u]].w-=aug;
                            e[cur[u]^1].w+=aug;
                        }
                        aug=inf;
                    }
                    break;
                }
            }
            if(flag)continue;
            int minlevel=NV;
            for(int i=head[u]; i!=-1; i=e[i].next) {
                int v=e[i].v;
                if(e[i].w&&level[v]<minlevel) {
                    minlevel=level[v];
                    cur[u]=i;
                }
            }
            if(--gap[level[u]]==0)break;
            level[u]=minlevel+1;
            gap[level[u]]++;
            u=pre[u];
        }
        return flow;
    }
    /**************************SAP**********************/
    int sum,x,num[55][55],id[55][55];
    bool judge(int i,int j)
    {
        return i>=1&&i<=n&&j>=1&&j<=m;
    }
    void build()
    {
        sum=x=0;NV=n*m+2;
        vs=0;vt=n*m+1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                x++;
                num[i][j]=read();
                sum+=num[i][j];
                id[i][j]=x;
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if((i+j)&1)
                {
                    addedge(id[i][j],vt,num[i][j]);
                }
                else
                {
                    addedge(vs,id[i][j],num[i][j]);
                    for(int x=-1;x<=1;x++)
                    for(int y=-1;y<=1;y++)
                    {
                        if(x+y==0||x==y||!judge(x+i,y+j))continue;
                        addedge(id[i][j],id[i+x][j+y],inf);
                    }
                }
            }
        }
    }
    int main()
    {
        while(scanf("%d%d",&n,&m)>0)
        {
            init();
            build();
            printf("%d
    ",sum-SAP());
        }
    }
    View Code
  • 相关阅读:
    2011年微软全球Next大赛闭幕。一站式示例代码库等30个项目获Microsoft Next殊荣
    微软一站式示例代码库(中文版)20110513版本, 新添加Windows Azure, WinForms等16个Sample
    发布:Visual Studio 2010 一站式示例代码搜索扩展
    微软一站式示例代码库 中文介绍视频发布 翻译得很幽默哦!
    六月新版微软一站式示例代码库发布 新增20个Windows示例代码
    Winform中使用打开文件对话框和文件夹浏览对话框
    二分查找
    求2个集合的交集
    自定义html代码运行框
    Winform中使用进度条的一个例子
  • 原文地址:https://www.cnblogs.com/lienus/p/4295318.html
Copyright © 2020-2023  润新知