zoukankan      html  css  js  c++  java
  • 【最大权闭合子图/最小割】BZOJ3438-小M的作物【待填】

    【题目大意】

    小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号),现在,第i种作物种植在A中种植可以获得ai的收益,在B中种植可以获得bi的收益,而且有m种作物组合,第i个组合中的作物共同种在A中可以获得c1i的额外收益,共同总在B中可以获得c2i的额外收益,所以,小M很快地算出了种植的最大收益。
     
    【思路】
    首先,如果没有组合方案应该怎么做呢?其实非常方便。
    首先建立超级源点S和超级汇点T,S向每个i连一条容量为ai的边,T向每个i连一条容量为bi的边。显然答案=总的容量之和-最小割。
    那么如果有了组合方案呢?
    对于每一个方案,我们可以拆为两个点u和v,由S向u连一条容量为c1i的边;由v向T连一条容量为c2i的边。然后由S向组合里的每一个点连一条容量为INF的边,由组合里的每一个点向T连一条容量为INF的边。显然割边必定会是和与S或者T相连接的点。
    可能这里会有一个疑惑:如果一个集合中的点的割边在和S相连的点中,而u,v的割边在和T相连的点中(也就是说我们把农作物种在了A中,却算了收益在B中。)
    事实上是——不可能的。我们可以证明:u、v和它们组合中的割边一定同时和S或者T连,否则必定有一条S到T的通路,就无法形成割了!
    所以最后答案=总的容量之和-最小割
    画画图就明白了:)
     
    ...T了,不知道为什么。
    删掉了STL部分。还是T了。我要静静。
    /*还是TLE,回头看*/
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define S 0
    #define T MAXN-1
    using namespace std;
    const int INF=0x7fffffff;
    const int MAXN=3000+50; 
    const int MAXM=4004000+50;
    struct node
    {
        int fr,to,pos,cap; 
    };
    int n,m,sum;
    int dis[MAXN];
    int vis[MAXN];
    int cur[MAXN];
    int first[MAXN],next[MAXM];
    node edge[MAXM];
    int tot=0;
    
    int read() {
        int x = 0;
        char ch = getchar();
        while (ch < '0' || '9' < ch)
            ch = getchar();
        while ('0' <= ch && ch <= '9') {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return x;
    }
    
    
    void addedge(int u,int v,int c)
    {
        edge[++tot]=(node){u,v,tot+1,c};
        next[tot]=first[u];first[u]=tot;
        edge[++tot]=(node){u,v,tot-1,0};
        next[tot]=first[v];first[v]=tot;
    }
    
    void build()
    {
        memset(first,-1,sizeof(first));
        memset(next,-1,sizeof(next));
        int ai,bi;
        n=read();
        for (int i=1;i<=n;i++) 
        {
            ai=read();
            sum+=ai;
            addedge(S,i,ai);
        }
        for (int i=1;i<=n;i++)
        {
            bi=read();
            sum+=bi;
            addedge(i,T,bi);
        }
        m=read();
        int k,c1i,c2i;
        for (int i=1;i<=m;i++)
        {
            k=read();c1i=read();c2i=read();
            int u=n+i;
            int v=n+i+m;
            addedge(S,u,c1i);
            addedge(v,T,c2i);
            sum+=c1i+c2i;
            for (int j=1;j<=k;j++)
            {
                int ci;
                ci=read();
                addedge(u,ci,INF);
                addedge(ci,v,INF);
            }
        }
    }
    
    int bfs()
    {
        memset(dis,-1,sizeof(dis));
        int l=0,r=0;
        int que[MAXN];
        que[++r]=S;
        dis[S]=0;
        
        while (l<r)
        {
            int head=que[l];l++;
            for (int i=first[head];i!=-1;i=next[i])
            {
                node &tmp=edge[i];
                if (dis[tmp.to]==-1 && tmp.cap>0)
                {
                    dis[tmp.to]=dis[head]+1;
                    que[++r]=tmp.to;
                }
            }
        }
        return (dis[T]!=-1);
    }
    
    int dfs(int s,int t,int f)
    {
        vis[s]=1;
        if (s==t || !f) return f;
        int res=0;
        for (int i=first[s];i!=-1;i=next[i])
        {
            node &tmp=edge[i];
            if (!vis[tmp.to] && tmp.cap>0 && dis[tmp.to]==dis[s]+1)
            {
                int delta=dfs(tmp.to,t,min(tmp.cap,f));
                if (delta>0)
                {
                    tmp.cap-=delta;
                    edge[tmp.pos].cap+=delta;
                    f-=delta;
                    res+=delta;
                    if (!f) return res;
                }
            }
        }
        return res;
    }
    
    int dinic()
    {
        int flow=0;
        while (bfs())
        {
            memset(vis,0,sizeof(vis));
            flow+=dfs(S,T,INF);
        }
        return flow;
    }
    
    int main()
    {
        build();
        printf("%d
    ",sum-dinic());
        return 0;
    }
  • 相关阅读:
    Golang相关环境变量
    mac catalina关闭系统更新提示
    Git常用命令
    UDP打洞原理
    LANMP相关配置
    Windows平台编译libevent
    Sublime text2 + cygwin编译C++
    C++的指针常量和常量指针
    C++的new和delete
    C/C++产生随机数
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5640104.html
Copyright © 2011-2022 走看看