• 【2021四川省赛】F-Direction Setting (费用流)


    思路

    最小费用最大流,把每条边看成一个点,和这条边连通的两点连边,流量为1,费用为0。
    超级起点和每条边都建一条边,同样流量为1,费用为0。
    每个点和超级汇点建两条边,一条流量为a[i],单位费用为0,一条流量为INF,单位费用为1,跑一遍最小费用。

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <list>
    #include <map>
    #include <iostream>
    #include <iomanip>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <unordered_map>
    #include <vector>
    #define LL long long
    #define inf 0x3f3f3f3f
    //#define INF 0x3f3f3f3f3f3f
    #define PI acos(-1.0)
    #define F first
    #define S second
    #define endl '
    '
    #define lson rt << 1
    #define rson rt << 1 | 1
    #define lowbit(x) (x & (-x))
    #define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
    #define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
    #define _per(i, a, b) for (int i = (a); i >= (b); --i)
    using namespace std;
    const int maxn = 3e3 + 7;
    const int maxm = 1e9 + 1;
    const LL mod = 1e9 + 7;
    int n, m;
    int a[maxn], b[maxn];
    namespace MCMF
    {
        const int MAXN = 1e3 + 7, MAXM = 3e3 + 7;
        int head[MAXN], cnt = 1;
        struct Edge
        {
            int to, w, c, next;
        } edges[MAXM * 2];
        inline void add(int from, int to, int w, int c)
        {
            edges[++cnt] = {to, w, c, head[from]};
            head[from] = cnt;
        }
        inline void addEdge(int from, int to, int w, int c)
        {
            add(from, to, w, c);
            add(to, from, 0, -c);
        }
        int s, t, dis[MAXN], cur[MAXN];
        bool inq[MAXN], vis[MAXN];
        queue<int> Q;
        bool SPFA()
        {
            while (!Q.empty())
                Q.pop();
            copy(head, head + MAXN, cur);
            fill(dis, dis + MAXN, inf);
            dis[s] = 0;
            Q.push(s);
            while (!Q.empty())
            {
                int p = Q.front();
                Q.pop();
                inq[p] = 0;
                for (int e = head[p]; e != 0; e = edges[e].next)
                {
                    int to = edges[e].to, vol = edges[e].w;
                    if (vol > 0 && dis[to] > dis[p] + edges[e].c)
                    {
                        dis[to] = dis[p] + edges[e].c;
                        if (!inq[to])
                        {
                            Q.push(to);
                            inq[to] = 1;
                        }
                    }
                }
            }
            return dis[t] != inf;
        }
        int dfs(int p = s, int flow = inf)
        {
            if (p == t)
                return flow;
            vis[p] = 1;
            int rmn = flow;
            for (int eg = cur[p]; eg && rmn; eg = edges[eg].next)
            {
                cur[p] = eg;
                int to = edges[eg].to, vol = edges[eg].w;
                if (vol > 0 && !vis[to] && dis[to] == dis[p] + edges[eg].c)
                {
                    int c = dfs(to, min(vol, rmn));
                    rmn -= c;
                    edges[eg].w -= c;
                    edges[eg ^ 1].w += c;
                }
            }
            vis[p] = 0;
            return flow - rmn;
        }
        int maxflow, mincost;
        inline void init()
        {
            cnt = 1;
            memset(head, 0, sizeof(head));
            maxflow = mincost = 0;
        }
        inline void run(int s, int t)
        {
            MCMF::s = s, MCMF::t = t;
            while (SPFA())
            {
                int flow = dfs();
                maxflow += flow;
                mincost += dis[t] * flow;
            }
        }
    }
    using namespace MCMF;
    int main()
    {
    
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t;
        cin >> t;
        while (t--)
        {
            cin >> n >> m;
            init();
            _rep(i, 1, n) cin >> a[i];
            int u, v;
            _rep(i, 1, m)
            {
                cin >> u >> v;
                b[i] = v;
                addEdge(n + m + 1, n + i, 1, 0);
                addEdge(n + i, u, 1, 0);
                addEdge(n + i, v, 1, 0);
            }
            _rep(i, 1, n)
            {
                addEdge(i, n + m + 2, a[i], 0);
                addEdge(i, n + m + 2, inf, 1);
            }
            run(n + m + 1, n + m + 2);
            cout << mincost << endl;
            _rep(i, n + 1, n + m)
            {
                for (int j = head[i]; j; j = edges[j].next)
                {
                    int v = edges[j].to;
                    if (edges[j].w)
                        continue;
                    if (v == b[i - n])
                        cout
                            << 0;
                    else
                        cout << 1;
                    break;
                }
            }
            cout << endl;
        }
    }
    
  • 相关阅读:
    130行C语言实现个用户态线程库(2)
    130行C语言实现个用户态线程库(1)
    用C语言模仿Python函数
    ES 2.4 bigdesk 安装失败解决方案.
    使用SqlBulkCopy, 插入整个DataTable中的所有数据到指定数据库中
    表A的数据减去表B ,最终得到表C
    关于把A表中的数据复制到B表中(整理)
    需求池整理
    app主流推广渠道
    流程图梳理
  • 原文地址:https://www.cnblogs.com/hfcdyp/p/15072218.html
Copyright © 2020-2023  润新知