zoukankan      html  css  js  c++  java
  • [SHOI 2007] 善意的投票

    [题目链接]

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

    [算法]

            首先 , 选择睡觉的人和不选择睡觉的人构成两个集合

            这启发我们用最小割解决该问题 :

            1. 将源点与每个睡觉的人连边 , 将每个不睡觉的人与汇点连边 , 割掉这样的一条边的含义是 : 有一个人放弃了睡觉 / 不睡觉 , 产生了1冲突

            2. 将朋友之间连边 , 割掉这样一条边的含义是 : 这两个人产生了冲突

            求解这个图的最小割即可

             时间复杂度 : O(dinic(N , M))

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    #define N 310
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int inf = 1e9;
    
    struct edge
    {
        int to , w , nxt;
    } e[N * N * 4];
    
    int tot , n , m , S , T;
    int head[N] , dep[N];
    
    template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
    template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
    template <typename T> inline void read(T &x)
    {
       T f = 1; x = 0;
       char c = getchar();
       for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
       for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
       x *= f;
    }
    inline void addedge(int u , int v , int w)
    {
        ++tot;
        e[tot] = (edge){v , w , head[u]};
        head[u] = tot;
        ++tot;
        e[tot] = (edge){u , 0 , head[v]};
        head[v] = tot;
    }
    inline bool bfs(int s)
    {
        queue< int > q;
        memset(dep , 255 , sizeof(dep));
        q.push(s);
        dep[s] = 1;
        while (!q.empty())
        {
            int cur = q.front();
            q.pop();
            for (int i = head[cur]; i; i = e[i].nxt)
            {
                int v = e[i].to , w = e[i].w;
                if (w > 0 && dep[v] == -1)
                {
                    dep[v] = dep[cur] + 1;
                    q.push(v);
                    if (v == T) return true;
                }
            }
        }
        return false;
    }
    inline int dinic(int u , int flow)
    {
        int rest = flow;
        if (u == T) 
            return flow;
        for (int i = head[u]; i && rest; i = e[i].nxt)
        {
            int v = e[i].to , w = e[i].w;
            if (w > 0 && dep[v] == dep[u] + 1)
            {
                int k = dinic(v , min(rest , w));
                if (!k) dep[v] = 0;
                rest -= k;
                e[i].w -= k;
                e[i ^ 1].w += k;
            }
        }
        return flow - rest;
    }
     
    int main()
    {
        
        read(n); read(m);
        tot = 1;
        S = n + 1 , T = S + 1;
        for (int i = 1; i <= n; i++)
        {
            int x;
            read(x);
            if (!x) addedge(S , i , 1);
            else addedge(i , T , 1);
        }
        for (int i = 1; i <= m; i++)
        {
            int x , y;
            read(x); read(y);
            addedge(x , y , 1);
            addedge(y , x , 1);
        }
        int ans = 0;
        while (bfs(S))
        {
            while (int flow = dinic(S , inf)) ans += flow;
        }
        printf("%d
    " , ans);
        
        return 0;
    }
  • 相关阅读:
    ASP.NET 实现邮件发送和接受的功能(Sockets)
    使用Sql server进行分布式查询
    Sqlserver中的一些技巧
    使用sql server中的全文索引
    水晶报表的装载和修改文本
    创建作业的通用存储过程
    MS SQL数据库备份和恢复
    数据库运用XML操作
    安装程序自动安装数据库
    ASP.NET 实现邮件发送和接受的功能(Mail)
  • 原文地址:https://www.cnblogs.com/evenbao/p/10355663.html
Copyright © 2011-2022 走看看