zoukankan      html  css  js  c++  java
  • [BZOJ 2768] 冠军调查

    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=2768

    Solution:

    一道比较基础的最大流的题目

    一般看到将点分为两类的题目就要往网络流方向想

    建图:

    源点向每个初始立场为1的人连权值为1的边。

    每个初始立场为0的人向汇点连权值为1的边。

    好朋友之间互相连权值为1的边。

    最小割即是答案。

    要满足要求且总和最小,就不能让任何一对(1,0)关系成立,这便对应着最小割模型

    割与源/汇点的边对应“说谎”,割二分图内部的边对应“立场不同”

    Code:

    //by NewErA
    #include <bits/stdc++.h>
    
    using namespace std;
    #define FF first
    #define SS second
    #define PB push_back
    #define MP make_pair
    #define bged(v) (v).begin(),(v).end()
    #define foreach(it,s) for(__typeof((s).begin()) it=(s).begin();it!=(s).end();it++)
    typedef long long ll;
    typedef pair<int,int> P;
    typedef pair<pair<int,int>,int> PP;
    const int INF=1<<27;
    const int MOD=1e9+7;
    //My IO system
    struct fastio
    {
        char s[100000];
        int it,len;
        fastio(){it=len=0;}
        inline char get()
        {
            if(it<len)return s[it++];it=0;
            len=fread(s,1,100000,stdin);
            if(len==0)return EOF;else return s[it++];
        }
        bool notend()
        {
            char c=get();
            while(c==' '||c=='
    ')c=get();
            if(it>0)it--;
            return c!=EOF;
        }
    }_buff;
    #define Read1(x) x=getnum()
    #define Read2(x,y) Read1(x),Read1(y)
    #define Read3(x,y,z) Read2(x,y),Read1(z)
    #define Write1(x) putnum(x),putchar('
    ')
    #define Write2(x,y) Write1(x),Write1(y)
    #define Write3(x,y,z) Write2(x,y),Write1(z)
    inline ll getnum()
    {
        ll r=0;bool ng=0;char c;c=_buff.get();
        while(c!='-'&&(c<'0'||c>'9'))c=_buff.get();
        if(c=='-')ng=1,c=_buff.get();
        while(c>='0'&&c<='9')r=r*10+c-'0',c=_buff.get();
        return ng?-r:r;
    }
    template<class T> inline void putnum(T x)
    {
        if(x<0)putchar('-'),x=-x;
        register short a[20]={},sz=0;
        while(x)a[sz++]=x%10,x/=10;
        if(sz==0)putchar('0');
        for(int i=sz-1;i>=0;i--)putchar('0'+a[i]);
    }
    
    const int MAXN=500;
    int n,m,s,t,level[MAXN],iter[MAXN],dat[MAXN];
    
    struct edge
    {
        int to,cap,rev;
    };
    vector<edge> a[MAXN];
    
    void add_edge(int to,int from,int cap)
    {
        a[to].push_back(edge{from,cap,a[from].size()});
        a[from].push_back(edge{to,cap,a[to].size()-1});
    }
    
    void bfs()
    {
        memset(level,-1,sizeof(level));
        queue<int> Q;Q.push(s);level[s]=0;
        while(!Q.empty())
        {
            int cur=Q.front();Q.pop();
            for(int i=0;i<a[cur].size();i++)
            {
                edge e=a[cur][i];
                if(e.cap && level[e.to]==-1)
                {
                    level[e.to]=level[cur]+1;
                    Q.push(e.to);
                }
            }
        }
    }
    
    int dfs(int v,int f)
    {
        if(v==t) return f;
        int ret=0;
        for(int &i=iter[v];i<a[v].size();i++)
        {
            edge &e=a[v][i];
            if(level[e.to]==level[v]+1 && e.cap)
            {
                int d=dfs(e.to,min(f,e.cap));
                f-=d;ret+=d;
                e.cap-=d;a[e.to][e.rev].cap+=d;            
                if(!f) break; 
            }
        }
        return ret;
    }
    
    int main()
    {
        Read2(n,m);s=n+1,t=s+1;
        for(int i=1;i<=n;i++)
        {
            Read1(dat[i]);
            if(dat[i]) add_edge(i,t,1);
            else add_edge(s,i,1);
        } 
        for(int i=1;i<=m;i++)
        {
            int x,y;Read2(x,y);
            if(dat[x]!=dat[y]) add_edge(x,y,1);
        }
        
        ll res=0;
        while(true)
        {
            memset(iter,0,sizeof(iter));
            bfs();int f=0;
            if(level[t]<0) break;
            res+=dfs(s,INF);
        }
        cout << res;
        return 0;
    }

    Review:

    很多时候碰到这样类似的二元关系就要往网络流方向想

    割的边容量即为计入答案的数值

  • 相关阅读:
    Git/GitHub使用技巧
    《暗时间》第一遍读书心得整理
    学习方法摘要总结
    Py爬虫项目
    2018年6月12日
    狐狸坑蛋糕
    Codeforces 371C Hanburgers
    【别忘咯】 关于运算优先级
    【noip 2009】 乌龟棋 记忆化搜索&动规
    【Openjudge】 算24
  • 原文地址:https://www.cnblogs.com/newera/p/9106101.html
Copyright © 2011-2022 走看看