zoukankan      html  css  js  c++  java
  • HDU 1565:最大点权独立集(网络流)

    题目要求我们选尽量多的点,同时两两不相邻

    可以想到把棋盘按照国际象棋的棋盘样式染色,那同一种颜色的点之间肯定是不相邻的,同时我们也就把图转化为了一个二分图

    题目要求也就变成了求这个二分图里的最大点权独立集

    最大独立集:包含尽量多顶点的集合,其中任意两点不相邻,所谓的不相邻也就是两点没有连边

    最小点覆盖:选取最少的点数,使这些点和所有的边都有关联(把所有的边的覆盖)

    最大点权独立集=总权值-最小点权覆盖集

    其实不难理解,看看定义就知道了

    假设现在已经求出了最小点覆盖,那把这些点去掉,剩下的点肯定是不相邻的,也就是说剩下的点可以构成一个独立集

    而我们现在求出的覆盖是最小的,所以自然得到的独立集也就是最大的了

    那问题就转化为了求最小点权覆盖集

    而二分图的最小点覆盖、最小点权覆盖集都可用网络流求解

    构图:

    超级源点与左边集合的每一点相连,若是求最小点覆盖,权值为1,若是求最小点权覆盖集,权值为该点的点权

    超级汇点与右边集合的每一点相连,权值同上

    然后将二分图原有的边加进图中,权值为无穷大

    #include"cstdio"
    #include"queue"
    #include"cmath"
    #include"stack"
    #include"iostream"
    #include"algorithm"
    #include"cstring"
    #include"queue"
    #include"map"
    #include"set"
    #include"vector"
    #define ll long long
    #define mems(a,b) memset(a,b,sizeof(a))
    #define ls pos<<1
    #define rs pos<<1|1
    
    using namespace std;
    const int MAXN = 500;
    const int MAXE = 40500;
    const int INF = 99999999;
    
    struct node{
        int s,e,next,cost,val;
        node(){}
        node(int a,int b,int c,int d):s(a),e(b),next(c),val(d){}
    }edge[MAXE];
    int tot,ans,n;
    int first[MAXN],dep[MAXN],gap[MAXN];
    int mat[50][50];
    int dx[4]={0,0,-1,1};
    int dy[4]={1,-1,0,0};
    
    void init(){
        tot=0;
        mems(first,-1);
    }
    
    void addedge(int u,int v,int w){
        //cout<<u<<'	'<<v<<'	'<<w<<endl;
        edge[tot]=node(u,v,first[u],w);
        first[u]=tot++;
        edge[tot]=node(v,u,first[v],0);
        first[v]=tot++;
    }
    
    int sap(int src,int des){
        memset(dep,0,sizeof(dep));
        memset(gap,0,sizeof(gap));
        gap[0]=des+1;
        int top=0,ans=0,u=src,i;
        int cur[MAXN],s[MAXE];
        //s[top++]=src;
        for(i=0;i<=des;i++)
            cur[i]=first[i];
        while(1){
            if(u==des){
                int minv=INF,pos;
                for(i=0;i<top;i++){
                    if(minv>edge[s[i]].val){
                        minv=edge[s[i]].val;
                        pos=i;
                    }
                }
                for(i=0;i<top;i++){
                    edge[s[i]].val-=minv;
                    edge[s[i]^1].val+=minv;
                }
                ans+=minv;
                top=pos;
                u=edge[s[pos]].s;
            }
            for(i=cur[u];i!=-1;i=edge[i].next)
                if(edge[i].val&&dep[u]==dep[edge[i].e]+1)
                    break;
            if(i!=-1){
                cur[u]=i;
                s[top++]=i;
                u=edge[i].e;
            }
            else{
                if(--gap[dep[u]]==0) break;
                int mindep=des+1;
                for(i=first[u];i!=-1;i=edge[i].next){
                    if(!edge[i].val) continue;
                    if(mindep>dep[edge[i].e]){
                        mindep=dep[edge[i].e];
                        cur[u]=i;
                    }
                }
                dep[u]=mindep+1;
                gap[dep[u]]++;
                if(u!=src) u=edge[s[--top]].s;
            }
        }
        return ans;
    }
    
    bool ing(int x,int y){
        if(x>=0&&x<n&&y>=0&&y<n) return true;
        return false;
    }
    
    int main(){
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&n)){
            init();
            int tot=0;
            for(int i=0;i<n;i++)
            for(int j=0;j<n;j++){
                scanf("%d",&mat[i][j]);
                tot+=mat[i][j];
            }
            int src=0;
            int des=n*n+1;
            for(int i=0;i<n;i++)
            for(int j=0;j<n;j++){
                if((i+j)%2==0) addedge(src,i*n+j+1,mat[i][j]);
                else addedge(i*n+j+1,des,mat[i][j]);
            }
            for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            if((i+j)%2==0)
            for(int k=0;k<4;k++){
                int x=i+dx[k];
                int y=j+dy[k];
                if(!ing(x,y)) continue;
                addedge(i*n+j+1,x*n+y+1,INF);
            }
            printf("%d
    ",tot-sap(src,des));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    数据库索引的作用和长处缺点
    Spring的依赖注入
    Spring+Ibatis集成开发实例
    IOS开发之类和对象
    关于C++ const 的全面总结
    包管理器Bower使用手冊之中的一个
    项目总算完工了
    git reset and git checkout
    unity3D中协程和线程混合
    【剑指offer】左旋转字符串
  • 原文地址:https://www.cnblogs.com/luxiaoming/p/5146566.html
Copyright © 2011-2022 走看看