• Prince and Princess HDU


    题面

    传送门

    前置

    这道题我感觉是这道题换过来的, 先写写这道题

    题解

    这道题比 POI1904 难在什么地方呢?

    首先没给预先的匹配关系, 那我们先跑一边最大匹配好了, 然后再按照 POI1904 写

    然而注意到, POI1904 是 n 个 王子 n 个公主, 这道题是 n 个王子和 m 个公主

    且存在某个王子娶不到公主, 某个公主也嫁不出去

    那咋办么?

    那就认为构造成 POI1904 的情况

    对所有没匹配上的王子, 添加一个虚拟的公主, 直接让二者匹配, 且其他王子也要喜欢这个虚拟公主(天下谁人不喜欢虚拟人呢?)

    对所有没匹配的上的公主, 添加一个虚拟的王子, 且这个虚拟王子喜欢所有的公主(恋与制作人喜欢所有的玩家)

    这样会出现什么情况呢? 王子,虚拟王子和公主,虚拟公主 都有可以匹配上的对象, 且每个人都可以至少和一个同性挖墙脚

    就和 POI1904 一样了, 直接有向图强连通缩点就行了, 至于为啥可以请移步

    代码

    int n, m, _, k;
    vector<VI> h;
    int c[N  << 2], scnt, st[N << 2], top;
    int dfn[N << 2], df, low[N << 2];
    bool inst[N << 2];
    
    void tarjan(int x) {
        dfn[x] = low[x] = ++df, inst[st[++top] = x] = 1;
        for (auto &y : h[x]) {
            if (!dfn[y]) { tarjan(y); umin(low[x], low[y]); }
            else if (inst[y]) umin(low[x], dfn[y]);
        }
        if (low[x] == dfn[x]) {
            ++scnt; int y;
            do { inst[y = st[top--]] = 0; c[y] = scnt; } while (x != y);
        }
    }
    
    VI match;
    vector<bool> v;
    
    bool dfs(int x) {
        for (auto &y : h[x]) {
            if (v[y - n]) continue; v[y - n] = 1;
            if (!match[y - n] || dfs(match[y - n])) return match[y - n] = x, 1;
        }
        return 0;
    }
    
    int main() {
        IOS; int cas = 0;
        for (cin >> _; _; --_) {
            cin >> n >> m; vector<VI>(n + m + 1).swap(h); VI(m + 1).swap(match);
            cout << "Case #" << ++cas << ":
    ";
            rep (i, 1, n) for (cin >> k; k; --k) { int v; cin >> v; h[i].pb(v + n); }
            vector<bool> boy(n + 1);
            rep (i, 1, n) { vector<bool>(m + 1).swap(v); boy[i] = dfs(i); }
            rep (i, 1, m) if (match[i]) h[i + n].pb(match[i]);
            rep (i, 1, n) if (!boy[i]) { 
                h.pb(VI(1, i)); h.back().pb(i);
                rep (j, 1, n) h[j].pb(h.size() - 1);
            }
            rep (i, 1, m) if (!match[i]) {
                h.pb(VI()); h[i + n].pb(h.size() - 1);
                rep (j, 1, m) h.back().pb(j + n);
            }
            memset(dfn, 0, sizeof dfn); df = scnt = 0;
            rep (i, 1, n + m) if (!dfn[i]) tarjan(i);
            rep (i, 1, n) {
                VI ans;
                for (auto &y : h[i]) if (c[y] == c[i] && y - n <= m) ans.pb(y - n);
                sort(all(ans)); cout << ans.size();
                for (auto &y : ans) cout << ' ' << y; cout << '
    ';
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Idea中创建maven项目
    安装axios
    配置路由
    安装Mock.js
    安装SCSS
    Incorrect username or password ( access token )
    Navicat使用笔记06Navicat Premium 12的安装、激活
    dump.rdb file All In One
    如何把闲置的 Mac mini 搭建成一个局域网中的 Web 服务器 All In One
    VSCode walkthroughs All In One
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/14113438.html
Copyright © 2020-2023  润新知