zoukankan      html  css  js  c++  java
  • 费用流 ZOJ 3933 Team Formation

    题目链接

    题意:两个队伍,有一些边相连,问最大组对数以及最多女生数量

    分析:费用流模板题,设置两个超级源点和汇点,边的容量为1,费用为男生数量.建边不能重复建边否则会T.zkw费用流在稠密图跑得快,普通的最小费用最大流也能过,只是相对来说慢了点

    #include <bits/stdc++.h>
    
    const int N = 5e2 + 5;
    const int INF = 0x3f3f3f3f;
    struct Min_Cost_Max_Flow {
        struct Edge {
            int from, to, cap, flow, cost;
        };
        std::vector<Edge> edges;
        std::vector<int> G[N];
        bool vis[N];
        int d[N], p[N], a[N];
        int n, m;
        
        void init(int n) {
            this->n = n;
            for (int i=0; i<=n; ++i) {
                G[i].clear ();
            }
            edges.clear ();
        }
        void add_edge(int from, int to, int cap, int cost)    {
            edges.push_back ((Edge) {from, to, cap, 0, cost});
            edges.push_back ((Edge) {to, from, 0, 0, -cost});
            m = edges.size ();
            G[from].push_back (m - 2);
            G[to].push_back (m - 1);
        }
        bool SPFA(int s, int t, int &flow, int &cost) {
            memset (d, INF, sizeof (d));
            memset (vis, false, sizeof (vis));
            memset (p, -1, sizeof (p));
            d[s] = 0; vis[s] = true; p[s] = 0; a[s] = INF;
    
            std::queue<int> que; que.push (s);
            while (!que.empty ()) {
                int u = que.front (); que.pop ();
                vis[u] = false;
                for (int i=0; i<G[u].size (); ++i)   {
                    Edge &e = edges[G[u][i]];
                    if (e.cap > e.flow && d[e.to] > d[u] + e.cost)   {
                        d[e.to] = d[u] + e.cost;
                        p[e.to] = G[u][i];
                        a[e.to] = std::min (a[u], e.cap - e.flow);
                        if (!vis[e.to])    {
                            vis[e.to] = true;
                            que.push (e.to);
                        }
                    }
                }
            }
    
            if (d[t] == INF) {
                return false;
            }
            flow += a[t];
            cost += d[t] * a[t];
            int u = t;
            while (u != s) {
                edges[p[u]].flow += a[t];
                edges[p[u]^1].flow -= a[t];
                u = edges[p[u]].from;
            }
            return true;
        }
        void run(int s, int t, int &flow, int &cost)    {
            flow = cost = 0;
            while (SPFA (s, t, flow, cost));
            
            printf ("%d %d
    ", flow, 2 * flow - cost);
            for (int i=0; i<edges.size (); i+=2) {
                if (edges[i].from == s || edges[i].to == t || edges[i].flow == 0) {
                    continue;
                }
                printf ("%d %d
    ", edges[i].from, edges[i].to);
            }
        }   
    };
    Min_Cost_Max_Flow mcmf;
    char group[N], sex[N];
    bool list[N];
    int n, m;
    
    int main() {
        int T; scanf ("%d", &T);
        while (T--) {
            scanf ("%d", &n);
            scanf ("%s", group + 1);
            scanf ("%s", sex + 1);
    
            mcmf.init (n + 1);
            int s = 0, t = n + 1;
            for (int i=1; i<=n; ++i) {
                if (group[i] == '0') {
                    mcmf.add_edge (s, i, 1, 0);
                } else {
                    mcmf.add_edge (i, t, 1, 0);
                }
                int m; scanf ("%d", &m);
                memset (list, false, sizeof (list));
                for (int j=1; j<=m; ++j) {
                    int v; scanf ("%d", &v);
                    list[v] = true;
                }
                if (group[i] == '1') {
                    continue;
                }
                int cost = (sex[i] == '1');
                for (int j=1; j<=n; ++j) {
                    if (list[j] || group[i] == group[j]) {
                        continue;
                    }
                    mcmf.add_edge (i, j, 1, cost + (sex[j] == '1'));
                }
            }
            int flow, cost;
            mcmf.run (s, t, flow, cost);
        }
    
        return 0;
    }
    

      

  • 相关阅读:
    redis:高可用分析
    mysql:explain分析sql
    python中注意事项(更新)
    jupyter使用小技巧(更新)
    Jupyter中的快捷键
    Excel制作甘特图
    Vim编辑器常用命令
    Mysql主从
    常用MySql命令
    进程与线程的一个简单解释
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5387367.html
Copyright © 2011-2022 走看看