• CF 103E Buying Sets 最大权闭合子图,匹配 难度:4


    http://codeforces.com/problemset/problem/103/E

    这道题首先一看就很像是最大权闭合子图,但是我们可以认为现在有两种点,数字和集合点,我们需要消除数字点的影响才能直接运用最大权闭合子图.

    进行二分匹配,使得每个集合都唯一匹配一个数字,买下一个集合点,则意味着该集合中所有数字的对应匹配集合点都要被买下,也就是可以建立一个新图,其中某个集合点向对应数字代表的集合点连单向边,可以证明对于任意权闭合子图中的集合点,集合中所有数字的对应匹配集合点都已经在这个权闭合子图中.对这个新图的所有价格取反,答案即最大权的负数

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=305;
    const int maxm=2*maxn+maxn*maxn;
    const int sups=303,supt=304;
    const int inf=0x6ffffff;
    
    int n;//original aspects
    int price[maxn];
    int st[maxn][maxn],nst[maxn];
    
    int mch[2*maxn];//Match
    bool vis[2*maxn];
    
    int first[maxn],elen;//maximum flow
    struct edge{
        int nxt,f,t,c;
    }e[maxm];
    int dis[maxn],gap[maxn];
    
    bool subMatch(int s){
        vis[s]=true;
        for(int j=0;j<nst[s];j++){
            int t=st[s][j]+n;
            if(vis[t]||mch[t]==s)continue;
            if(mch[t]==0||(!vis[mch[t]]&&subMatch(mch[t]))){
                mch[t]=s;
                mch[s]=t;
                return true;
            }
        }
        return false;
    }
    void Match(){
        for(int i=1;i<=n;i++){
            if(mch[i]==0){
                memset(vis,false,sizeof(vis));
                subMatch(i);
            }
        }
    }
    
    void addedge(int f,int t,int c){
        e[elen].nxt=first[f];
        e[elen].f=f;
        e[elen].t=t;
        e[elen].c=c;
        first[f]=elen++;
    }
    void build(){
        for(int i=1;i<=n;i++){
            if(price[i]>=0){
                addedge(sups,i,price[i]);
                addedge(i,sups,0);
            }
            else {
                addedge(i,supt,-price[i]);
                addedge(supt,i,0);
            }
            for(int j=0;j<nst[i];j++){
                int t=mch[st[i][j]+n];
                addedge(i,t,inf);
                addedge(t,i,0);
            }
        }
    }
    int dfs(int s,int flow){
        if(s==supt)return flow;
        int mindis=n;
        int tflow=flow,sub;
        for(int p=first[s];p!=-1;p=e[p].nxt){
            int t=e[p].t;
            if(e[p].c>0){
                if(dis[t]+1==dis[s]){
                    sub=dfs(t,min(tflow,e[p].c));
                    e[p].c-=sub;e[p^1].c+=sub;
                    tflow-=sub;
                    if(dis[sups]>n)return flow-tflow;
                    if(tflow<=0)break;
                }
                mindis=min(mindis,dis[t]);
            }
        }
        if(flow==tflow){
            --gap[dis[s]];
            if(gap[dis[s]]==0)dis[sups]=n+1;
            else{
                dis[s]=mindis+1;
                ++gap[dis[s]];
            }
        }
        return flow-tflow;
    }
    int maxflow(){
        int flow=0;
        gap[0]=n+2;
        while(dis[sups]<=n){
            flow+=dfs(sups,inf);
        }
        return flow;
    }
    
    int main(){
        int ans=0;
        memset(first,-1,sizeof(first));
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",nst+i);
            for(int j=0;j<nst[i];j++){
                scanf("%d",st[i]+j);
            }
        }
        for(int i=1;i<=n;i++){
            scanf("%d",price+i);
            price[i]*=-1;
            if(price[i]>=0)ans+=price[i];
        }
    
        Match();
        build();
        ans=maxflow()-ans;
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    spring的IOC和AOP协同工作
    微博mid和id转换
    java classpath getResource getResourceAsStream
    spring和mybatis集成,自动生成model、mapper,增加mybatis分页功能
    java notify和notifyAll的区别
    embedded tomcat context.xml
    RESTful框架调研
    BFC以及文档流
    ace 读取excel
    iis 下的 selfssl
  • 原文地址:https://www.cnblogs.com/xuesu/p/4418868.html
Copyright © 2020-2023  润新知