• 【BZOJ-2768】冠军调查 最小割


    2768: [JLOI2010]冠军调查

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 971  Solved: 661
    [Submit][Status][Discuss]

    Description

    一年一度的欧洲足球冠军联赛已经进入了淘汰赛阶段。随着卫冕冠军巴萨罗那的淘汰,英超劲旅切尔西成为了头号热门。新浪体育最近在吉林教育学院进行了一次大规模的调查,调查的内容就是关于切尔西能否在今年问鼎欧洲冠军。新浪体育的记者从各个院系中一共抽取了n位同学作为参与者,大家齐聚一堂,各抒己见。每一位参与者都将发言,阐述自己的看法。参与者的心里都有一个看法,比如FireDancer认为切尔西不可能夺冠,而WaterDancer认为切尔西一定问鼎。但是因为WaterDancer是FireDancer的好朋友,所以可能FireDancer为了迁就自己的好朋友,会在发言中支持切尔西。也就是说每个参与者发言时阐述的看法不一定就是心里所想的。现在告诉你大家心里的想法和参与者的朋友网,希望你能安排每个人的发言内容,使得违心说话的人的总数与发言时立场不同的朋友(对)的总数的和最小。
     

    Input

    第一行两个整数n和m,其中n(2≤n≤300)表示参与者的总数,m(0≤m≤n(n-1)/2)表示朋友的总对数。
    第二行n个整数,要么是0要么是1。如果第i个整数的值是0的话,表示第i个人心里认为切尔西将与冠军无缘,如果是1的话,表示他心里认为切尔西必将夺魁。
    下面m行每行两个不同的整数,i和j(1≤i, j≤n)表示i和j是朋友。注意没有一对朋友会在输入中重复出现。朋友关系是双向的,并且不会传递。
     

    Output

     
    只有一个整数,为最小的和。

    Sample Input

    3 3
    1 0 0
    1 2
    1 3
    2 3

    Sample Output

    1

    HINT

    最好的安排是所有人都在发言时说切尔西不会夺冠。这样没有一对朋友的立场相左,只有第1个人他违心说了话。

    Source

    Solution

    比较简单的最小割

    设S集合为支持集,T集合为不支持集

    对于所有支持的人,被S连;所有不支持的人,向T连

    朋友之间互相连

    容量全部为1

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    #define MAXN 1010
    #define MAXM 1000010
    struct EdgeNode{int next,to,cap;}edge[MAXM];
    int head[MAXN],cnt=1,S,T;
    void add(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;}
    void insert(int u,int v,int w) {add(u,v,w); add(v,u,0);} 
    int N,M;
    int cur[MAXN],h[MAXN];
    #define inf 0x7fffffff
    bool bfs()
    {
        queue<int>q;
        for (int i=S; i<=T; i++) h[i]=-1;
        h[S]=1; q.push(S);
        while (!q.empty())
            {
                int now=q.front(); q.pop();
                for (int i=head[now]; i; i=edge[i].next)
                    if (h[edge[i].to]==-1 && edge[i].cap)
                        h[edge[i].to]=h[now]+1,q.push(edge[i].to);
            }
        return h[T]!=-1;        
    }
    int dfs(int loc,int low)
    {
        if (loc==T) return low;
        int used=0,w;
        for (int i=cur[loc]; i; i=edge[i].next)
            if (edge[i].cap && h[edge[i].to]==h[loc]+1)
                {
                    w=dfs(edge[i].to,min(edge[i].cap,low-used));
                    edge[i].cap-=w; edge[i^1].cap+=w; used+=w;
                    if (used==low) return low;
                    if (edge[i].to) cur[loc]=i;
                }
        if (!used) h[loc]=-1;
        return used;
    }
    int dinic()
    {
        int tmp=0;
        while (bfs())
            {
                for (int i=S; i<=T; i++) cur[i]=head[i];
                tmp+=dfs(S,inf);
            }
        return tmp;
    }
    int main()
    {
        N=read(); M=read();
        S=0,T=N+1;
        for (int x,i=1; i<=N; i++)
             {
                 x=read();
                 if (x) insert(S,i,1);
                 else insert(i,T,1);
             }
        for (int x,y,i=1; i<=M; i++)
            {
                x=read(),y=read();
                insert(x,y,1); insert(y,x,1);
            }
        printf("%d
    ",dinic());
        return 0;
    }
  • 相关阅读:
    WNMP 环境搭建
    单元测试工具 unitils
    [转] 利用git钩子,使用python语言获取提交的文件列表
    Spring AOP理解
    JavaScript Cookies使用
    [转]SURF算法解析
    [转]四旋翼飞行器的姿态解算小知识点
    [转]C++内存管理
    学习SQL笔记
    华为软件类常见面试问题集锦
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5678962.html
Copyright © 2020-2023  润新知