• BZOJ1934 [Shoi2007]Vote 善意的投票 【最小割】


    题目

    幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉。对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神。虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投和自己本来意愿相反的票。我们定义一次投票的冲突数为好朋友之间发生冲突的总数加上和所有和自己本来意愿发生冲突的人数。 我们的问题就是,每位小朋友应该怎样投票,才能使冲突数最小?

    输入格式

    第一行只有两个整数n,m,保证有2≤n≤300,1≤m≤n(n-1)/2。其中n代表总人数,m代表好朋友的对数。文件第二行有n个整数,第i个整数代表第i个小朋友的意愿,当它为1时表示同意睡觉,当它为0时表示反对睡觉。接下来文件还有m行,每行有两个整数i,j。表示i,j是一对好朋友,我们保证任何两对i,j不会重复。

    输出格式

    只需要输出一个整数,即可能的最小冲突数。

    输入样例

    3 3

    1 0 0

    1 2

    1 3

    3 2

    输出样例

    1

    解释

    在第一个例子中,所有小朋友都投赞成票就能得到最优解

    题解

    我们设源汇点S、T,S向赞成的小朋友连边,不赞成的向T连边,好友之间互相连边,容量均为1
    此时求最小割即为答案
    对于任意一一对好友,他们要么在同一边,要么二者断开【好友冲突】,要么其中一者与源汇点断开【改变意愿】

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define Redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)
    using namespace std;
    const int maxn = 305,maxm = 300005,INF = 1000000000;
    inline int RD(){
        int out = 0,flag = 1; char c = getchar();
        while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
        while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
        return out * flag;
    }
    int h[maxn],ne = 0,N,M,d[maxn],vis[maxn],cur[maxn],S,T;
    struct EDGE{int to,nxt,f;}ed[maxm];
    inline void build(int u,int v,int w){
        ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;
        ed[ne] = (EDGE){u,h[v],0}; h[v] = ne++;
    }
    bool bfs(){
        queue<int> q;
        for (int i = S; i <= T; i++) vis[i] = false,d[i] = INF;
        d[S] = 0; q.push(S); int to,u;
        while (!q.empty()){
            u = q.front(); q.pop();
            Redge(u) if (ed[k].f && !vis[to = ed[k].to]){
                d[to] = d[u] + 1; vis[to] = true;
                q.push(to);
            }
        }
        return vis[T];
    }
    int dfs(int u,int minf){
        if (u == T || !minf) return minf;
        int flow = 0,f,to;
        if (cur[u] == -2) cur[u] = h[u];
        for (int& k = cur[u]; k != -1; k = ed[k].nxt)
            if (d[to = ed[k].to] == d[u] + 1 && (f = dfs(to,min(minf,ed[k].f)))){
                ed[k].f -= f; ed[k ^ 1].f += f;
                flow += f; minf -= f;
                if (!minf) break;
            }
        return flow;
    }
    int maxflow(){
        int flow = 0;
        while (bfs()){
            fill(cur,cur + maxn,-2);
            flow += dfs(S,INF);
        }
        return flow;
    }
    int main(){
        memset(h,-1,sizeof(h));
        N = RD(); M = RD(); S = 0; T = N + 1; int a,b;
        REP(i,N) if (RD()) build(S,i,1); else build(i,T,1);
        while (M--){
            a = RD(); b = RD();
            build(a,b,1); build(b,a,1);
        }
        printf("%d",maxflow());
        return 0;
    }
    
  • 相关阅读:
    CSS的学习
    nodejs
    eureka注册中心
    netty的机制
    分布式事务
    spring cloud的基础
    一个发散动画的菜单控件(主要记录控件x,y坐标的运动状况)
    关于ViewPager高度自适应(随着pager页的高度改变Viewpager的高度)
    ViewPager的使用总结
    Android实现沉浸式状态栏(必须高逼格)
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282746.html
Copyright © 2020-2023  润新知