zoukankan      html  css  js  c++  java
  • 【BZOJ1934】善意的投票(SHOI2007)-最小割

    测试地址:善意的投票
    做法:本题需要用到最小割。
    大家好,本图论渣渣又来做网络流基础题了……
    尝试把本题转化为最小割模型。首先,从源点向每一个同意的点连一条容量为1的边,从每一个反对的点向汇点连一条容量为1的边。然后对于每一对朋友,如果两人意见不同,那么从同意的向反对的连一条容量为1的边,否则它们应该相互都要连一条容量为1的边。
    这个模型有什么意义呢?一般的最小割模型中,我们都会以从源点能不能到达这个点为依据,将所有点分成两个集合。那么在这道题中,从源点能到达的点就表示投赞成票,反之表示投反对票。对于每一对朋友,他们要么意见相同(即处于同一个集合内),意味着割掉他们中一员和源汇点之间的边,要么他们就会产生冲突,意味着割掉他们之间的边。那么问题就变成求一个最小割,这就很好解决了。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int inf=1000000000;
    int n,m,x[310],S,T,tot=1,first[310]={0};
    int h,t,q[310],lvl[310];
    struct edge
    {
        int v,next;
        int f;
    }e[200010];
    
    void insert(int a,int b,int f)
    {
        e[++tot].v=b,e[tot].next=first[a],e[tot].f=f,first[a]=tot;
        e[++tot].v=a,e[tot].next=first[b],e[tot].f=0,first[b]=tot;
    }
    
    void init()
    {
        scanf("%d%d",&n,&m);
        S=n+1,T=n+2;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x[i]);
            if (x[i]) insert(S,i,1);
            else insert(i,T,1);
        }
        for(int i=1;i<=m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            if (x[a]!=x[b])
            {
                if (!x[a]) swap(a,b);
                insert(a,b,1);
            }
            else insert(a,b,1),insert(b,a,1);
        }
    }
    
    bool makelevel()
    {
        for(int i=1;i<=T;i++)
            lvl[i]=-1;
        lvl[S]=0;
        h=t=1;
        q[1]=S;
        while(h<=t)
        {
            int v=q[h++];
            for(int i=first[v];i;i=e[i].next)
                if (e[i].f&&lvl[e[i].v]==-1)
                {
                    lvl[e[i].v]=lvl[v]+1;
                    q[++t]=e[i].v;
                }
        }
        return lvl[T]!=-1;
    }
    
    int maxflow(int v,int maxf)
    {
        int ret=0,f;
        if (v==T) return maxf;
        for(int i=first[v];i;i=e[i].next)
            if (e[i].f&&lvl[e[i].v]==lvl[v]+1)
            {
                f=maxflow(e[i].v,min(maxf-ret,e[i].f));
                ret+=f;
                e[i].f-=f;
                e[i^1].f+=f;
            }
        return ret;
    }
    
    void dinic()
    {
        int maxf=0;
        while(makelevel())
        {
            int f=maxflow(S,inf);
            maxf+=f;
        }
        printf("%d",maxf);
    }
    
    int main()
    {
        init();
        dinic();
    
        return 0;
    }
  • 相关阅读:
    python3.6+requests实现接口自动化4
    python3.6+requests实现接口自动化3
    Druid学习之路 (五)Druid的数据摄取任务类型
    Druid学习之路 (四)Druid的数据采集格式
    Druid学习之路 (三)Druid的数据源和段
    Druid学习之路 (二)Druid架构
    Druid学习之路 (一)Druid初识
    Hive sql和Presto sql的一些对比
    Pyspark的HBaseConverters详解
    Pyspark访问Hbase
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793450.html
Copyright © 2011-2022 走看看