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:

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

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

  • 相关阅读:
    PAT顶级 1015 Letter-moving Game (35分)
    PAT顶级 1008 Airline Routes (35分)(有向图的强连通分量)
    PAT顶级 1025 Keep at Most 100 Characters (35分)
    PAT顶级 1027 Larry and Inversions (35分)(树状数组)
    PAT 顶级 1026 String of Colorful Beads (35分)(尺取法)
    PAT顶级 1009 Triple Inversions (35分)(树状数组)
    Codeforces 1283F DIY Garland
    Codeforces Round #438 A. Bark to Unlock
    Codeforces Round #437 E. Buy Low Sell High
    Codeforces Round #437 C. Ordering Pizza
  • 原文地址:https://www.cnblogs.com/newera/p/9106101.html
Copyright © 2011-2022 走看看