zoukankan      html  css  js  c++  java
  • [ZJOI2009] 假期的宿舍

    [ZJOI2009] 假期的宿舍

    Description

    每个人只能睡和自己直接认识的人的床,有 (n) 个人,每个人可能是在校学生或者不是,可能回家也可能不回,判断是否存在一个方案使得不回家的在校学生和非本校学生都有地方住。

    Solution

    二分图匹配,人 (i) 和人 (j) 如果认识,那么人 (i) 就和床 (j) 连边。注意人 (i) 和床 (i) 之间要额外连边。如果 (i) 是本校学生,那么床 (i) 和汇点之间连边;如果 (i) 不是在校学生或者 (i) 不回家,那么源点和人 (i) 之间连边,表示他需要一张床。

    编号分配:源点 (1),汇点 (2),第 (i) 个人编号 (3+i),第 (i) 个人对应的床(假设存在,如果没有这张床那么就不和汇点连边)编号为 (3+n+i)

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    
    #ifndef __FLOW_HPP__
    #define __FLOW_HPP__
    
    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    
    namespace flowsolution
    {
        const int N = 1005;
        const int M = 10005;
        const int inf = 1e+12;
    
        struct MaxflowSolution
        {
            int *dis, ans, cnt = 1, s, t, *pre, *next, *head, *val;
    
            MaxflowSolution()
            {
                cnt = 1;
                dis = new int[N];
                pre = new int[M];
                next = new int[M];
                head = new int[N];
                val = new int[M];
                fill(dis, dis + N, 0);
                fill(pre, pre + M, 0);
                fill(next, next + M, 0);
                fill(head, head + N, 0);
                fill(val, val + M, 0);
            }
    
            ~MaxflowSolution()
            {
                delete[] dis;
                delete[] pre;
                delete[] next;
                delete[] head;
                delete[] val;
            }
    
            std::queue<int> q;
            void make(int x, int y, int z)
            {
                pre[++cnt] = y, next[cnt] = head[x], head[x] = cnt, val[cnt] = z;
                pre[++cnt] = x, next[cnt] = head[y], head[y] = cnt;
            }
    
            bool bfs()
            {
                fill(dis, dis + N, 0);
                q.push(s), dis[s] = 1;
                while (!q.empty())
                {
                    int x = q.front();
                    q.pop();
                    for (int i = head[x]; i; i = next[i])
                        if (!dis[pre[i]] && val[i])
                            dis[pre[i]] = dis[x] + 1, q.push(pre[i]);
                }
                return dis[t];
            }
    
            int dfs(int x, int flow)
            {
                if (x == t || !flow)
                    return flow;
                int f = flow;
                for (int i = head[x]; i; i = next[i])
                    if (val[i] && dis[pre[i]] > dis[x])
                    {
                        int y = dfs(pre[i], min(val[i], f));
                        f -= y, val[i] -= y, val[i ^ 1] += y;
                        if (!f)
                            return flow;
                    }
                if (f == flow)
                    dis[x] = -1;
                return flow - f;
            }
    
            int solve(int _s, int _t)
            {
                s = _s;
                t = _t;
                ans = 0;
                for (; bfs(); ans += dfs(s, inf));
                return ans;
            }
        };
    
        struct CostflowSolution
        {
            struct Edge
            {
                int p = 0, c = 0, w = 0, next = -1;
            } * e;
            int s, t, tans, ans, cost, ind, *bus, qhead = 0, qtail = -1, *qu, *vis, *dist;
    
            CostflowSolution()
            {
                e = new Edge[M];
                qu = new int[M];
                bus = new int[N];
                vis = new int[N];
                dist = new int[N];
                fill(qu, qu + M, 0);
                fill(bus, bus + N, 0);
                fill(vis, vis + N, 0);
                fill(dist, dist + N, 0);
                ind = 0;
            }
    
            ~CostflowSolution()
            {
                delete[] e;
                delete[] qu;
                delete[] vis;
                delete[] dist;
            }
    
            void graph_link(int p, int q, int c, int w)
            {
                e[ind].p = q;
                e[ind].c = c;
                e[ind].w = w;
                e[ind].next = bus[p];
                bus[p] = ind;
                ++ind;
            }
    
            void make(int p, int q, int c, int w)
            {
                graph_link(p, q, c, w);
                graph_link(q, p, 0, -w);
            }
    
            int dinic_spfa()
            {
                qhead = 0;
                qtail = -1;
                fill(vis, vis + N, 0);
                fill(dist, dist + N, inf);
                vis[s] = 1;
                dist[s] = 0;
                qu[++qtail] = s;
                while (qtail >= qhead)
                {
                    int p = qu[qhead++];
                    vis[p] = 0;
                    for (int i = bus[p]; i != -1; i = e[i].next)
                        if (dist[e[i].p] > dist[p] + e[i].w && e[i].c > 0)
                        {
                            dist[e[i].p] = dist[p] + e[i].w;
                            if (vis[e[i].p] == 0)
                                vis[e[i].p] = 1, qu[++qtail] = e[i].p;
                        }
                }
                return dist[t] < inf;
            }
    
            int dinic_dfs(int p, int lim)
            {
                if (p == t)
                    return lim;
                vis[p] = 1;
                int ret = 0;
                for (int i = bus[p]; i != -1; i = e[i].next)
                {
                    int q = e[i].p;
                    if (e[i].c > 0 && dist[q] == dist[p] + e[i].w && vis[q] == 0)
                    {
                        int res = dinic_dfs(q, min(lim, e[i].c));
                        cost += res * e[i].w;
                        e[i].c -= res;
                        e[i ^ 1].c += res;
                        ret += res;
                        lim -= res;
                        if (lim == 0)
                            break;
                    }
                }
                return ret;
            }
    
            pair<int, int> solve(int _s, int _t)
            {
                s = _s;
                t = _t;
                ans = 0;
                cost = 0;
                while (dinic_spfa())
                {
                    fill(vis, vis + N, 0);
                    ans += dinic_dfs(s, inf);
                }
                return make_pair(ans, cost);
            }
        };
    } // namespace flowsolution
    
    #endif
    
    void solve()
    {
        int n;
        cin >> n;
    
        vector<int> is_student(n + 2);
        vector<int> is_away(n + 2);
        vector<vector<int>> is_related(n + 2, vector<int>(n + 2));
    
        for (int i = 1; i <= n; i++)
            cin >> is_student[i];
        for (int i = 1; i <= n; i++)
            cin >> is_away[i];
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                cin >> is_related[i][j];
    
        int S = 1, T = 2;
        auto id_person = [&](int i) -> int {
            return i + 3;
        };
        auto id_bed = [&](int i) -> int {
            return i + n + 3;
        };
    
        flowsolution::MaxflowSolution flow;
    
        int tot = 0;
    
        for (int i = 1; i <= n; i++)
            if (is_student[i])
                flow.make(id_bed(i), T, 1);
        for (int i = 1; i <= n; i++)
            if (!is_student[i] || !is_away[i])
                flow.make(S, id_person(i), 1), ++tot;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                if (i == j || is_related[i][j])
                    flow.make(id_person(i), id_bed(j), 1);
    
    
        cout << (flow.solve(S, T) == tot ? "^_^" : "T_T") << endl;
    }
    
    signed main()
    {
        // ios::sync_with_stdio(false);
    
        int t;
        cin >> t;
    
        while (t--)
        {
            solve();
        }
    }
    
  • 相关阅读:
    per-CPU变量
    oom killer
    System.map文件的作用
    Linux电源管理(9)_wakelocks【转】
    Linux内核的冷热缓存
    浅谈TCP IP协议栈(四)IP协议解析
    浅谈TCP IP协议栈(三)路由器简介
    CFS调度器(1)-基本原理
    浅谈TCP IP协议栈(二)IP地址
    (利用DOM)在新打开的页面点击关闭当前浏览器窗口
  • 原文地址:https://www.cnblogs.com/mollnn/p/14339015.html
Copyright © 2011-2022 走看看