zoukankan      html  css  js  c++  java
  • B1934 [Shoi2007]Vote 善意的投票 最小割

    一开始不太会,结果看完题解就是一个建图的网络流。然后就结了。

    题干:

    题目描述
    
    幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。
    
    我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?
    
    输入输出格式
    
    输入格式:
    文件的第一行只有两个整数n,m,保证有2≤n≤3001≤m≤n(n-1)/2。其中n代表总人数,m代表好朋友的对数。文件第二行有n个整数,第i个整数代表第i个小朋友的意愿,当它为1时表示同意睡觉,当它为0时表示反对睡觉。接下来文件还有m行,每行有两个整数i,j。表示i,j是一对好朋友,我们保证任何两对i,j不会重复。
    
    输出格式:
    只需要输出一个整数,即可能的最小冲突数。
    
    输入输出样例
    
    输入样例#1: 复制
    3 3
    1 0 0
    1 2
    1 3
    3 2
    输出样例#1: 复制
    1
    说明
    
    2≤n≤3001≤m≤n(n-1)/2

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    #define inf 99999999
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(),c > '9' || c < '0')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(),c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op == 1)
            x = -x;
    }
    struct node{
        int x,y,c,nxt,other;
    };
    node a[21110000];
    int len = 0,last[5000],st,ed;
    int list[5000];
    void add(int x,int y,int w)
    {
        int k1,k2;
        a[++len].nxt = last[x];
        k1 = len;
        a[len].x = x;
        a[len].y = y;
        a[len].c = w;
        last[x] = len;
        a[++len].nxt = last[y];
        k2 = len;
        a[len].x = y;
        a[len].y = x;
        a[len].c = w;
        last[y] = len;
        a[k1].other = k2;
        a[k2].other = k1;
    }
    int h[5001];
    bool bfs()
    {
        memset(h,0,sizeof(h));
        h[st] = 1;
        int head,tail;
        list[1] = st;
        head = 1;
        tail = 2;
        while(head != tail)
        {
            int x = list[head];
            for(int k = last[x];k;k = a[k].nxt)
            {
                int y = a[k].y;
                if(a[k].c > 0 && h[y] == 0)
                {
                    h[y] = h[x] + 1;
                    list[tail++] = y;
                }
            }
            head++;
        }
        if(h[ed] > 0)
        return true;
        else
        return false;
    }
    int find(int x,int f)
    {
        if(x == ed)
        {
            return f;
        }
        int s = 0,t;
        for(int k = last[x];k;k = a[k].nxt)
        {
            int y = a[k].y;
            if(s < f && h[y] == (h[x] + 1) && a[k].c > 0)
            {
                t = find(y,min(a[k].c,f - s));
                s += t;
                a[k].c -= t;
                a[a[k].other].c += t;
            }
        }
        if(s == 0)
        h[x] = 0;
        return s;
    }
    int n,m;
    int main()
    {
        read(n);read(m);
        int x,y;
        st = 0;
        ed = 520;
        duke(i,1,n)
        {
            read(x);
            if(x == 1)
            {
                add(st,i,1);
            }
            else
            {
                add(i,ed,1);
            }
        }
        duke(i,1,m)
        {
            read(x);read(y);
            add(x,y,1);
        }
        int tot = 0;
        while(bfs())
        {
            tot += find(st,inf);
        }
        printf("%d",tot);
        return 0;
    }
  • 相关阅读:
    C++中类模板的概念和意义
    欢迎访问新博客aiyoupass.com
    P2327
    P2885
    P1968
    Link-Cut-Tree
    树的重心
    点分治笔记
    SPOJ 375
    树链剖分
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9676472.html
Copyright © 2011-2022 走看看