小红开宝箱

时间限制:1秒 空间限制:256M

网页链接

牛客tracker

牛客tracker & 每日一题,完成每日打卡,即可获得牛币。获得相应数量的牛币,能在【牛币兑换中心】,换取相应奖品!助力每日有题做,丰盈牛币日益多!
在这里插入图片描述

题目描述

小红来到了一个宝箱面前,但这个宝箱上锁了,开这个宝箱需要进行解密。

解密的方式是:给出了 n n n 根柱子,小红必须按照规定的次序依次击打这 n n n 根柱子。

现在小红通过贿赂地下城的设计者小紫,得出了每次应击打的柱子的可能性。小红想让你帮忙设计一个击打顺序,使得该顺序和小紫给出的信息不冲突。

输入描述:

第一行输入一个正整数 n n n ,代表柱子的数量。
接下来的 n n n 行,每行首先输入一个正整数 k i k_i ki ​,代表对于第 i i i 次击打小紫给出的信息(柱子的可能性)数量。紧接着是 k i k_i ki 个正整数 p i j p_ij pij ​,代表该次击打有可能是哪一个柱子。
1 ≤ n ≤ 10 5 1≤n≤10^5 1n105
1 ≤ k i ≤ 2 1≤k_i≤2 1ki2
1 ≤ p i j ≤ n 1≤p_{ij}≤n 1pijn

输出描述:

如果不存在一个合法解,代表小紫欺骗了小红,请输出 " k o u i s a n g r y " "kou is angry" "kouisangry" 。否则输出一个长度为 n n n 的排列,代表一个合法的击打序列。有多解时输出任意即可。

示例1

输入:

3
1 2
2 1 3
2 1 3

输出:

2 1 3

说明:

输出 2   3   1 2 \ 3 \ 1 2 3 1 也是可以的。

解题思路

本题核心是二分图最大匹配求解合法击打序列:问题本质是为n个击打位置分配n个互不重复的柱子,且第i个位置只能选择指定的 1   ˜ 2 1 \~\ 2 1 ˜2 个柱子,等价于求解二分图的完美匹配。构建二分图,左部节点为击打位置,右部节点为柱子,为每个位置向其可选的柱子连边;采用匈牙利算法求解最大匹配,若匹配数等于n,则存在合法解,否则输出无解。根据匹配结果映射关系,直接输出合法的排列即可。由于每个位置最多连 2 2 2 条边,算法效率极高,完美适配n≤1e5的大数据规模。

总结

  1. 核心逻辑:将分配问题转化为击打位置-柱子的二分图完美匹配问题。
  2. 关键操作:匈牙利算法求解最大匹配,匹配数为n则构造解,否则判定无解。
  3. 效率保障:每个节点边数不超过 2 2 2 ,算法运行速度快,满足题目时间限制。

代码内容

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef vector<vector<ll>> vt;
typedef pair<ll,ll> pll;
const ll N=2e5+10;
const ll mod=1e9+7;
const ll INF=1e18;
bool v[N];
ll m[N];
vector<ll> tr[N];

bool dfs(ll x)
{
    for(auto& to:tr[x])
    {
        if(v[to]) continue;
        v[to]=1;

        if(!m[to]||dfs(m[to]))
        {
            m[to]=x;
            return 1;
        }
    }
    return 0;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    ll n;
    cin>>n;
    for(ll i=1;i<=n;i++)
    {
        ll k;cin>>k;
        for(ll j=1;j<=k;j++)
        {
            ll x;
            cin>>x;
            tr[x].push_back(i+n);
        }
    }

    ll ans=0;
    for(ll i=1;i<=n;i++)
    {
        memset(v,0,sizeof v);
        if(dfs(i)) ans++;
    }

    if(ans!=n)
    {
        cout<<"kou is angry"<<endl;
        return 0;
    }

    for(ll i=1;i<=n;i++) cout<<m[i+n]<<" ";
    cout<<endl;

    return 0;
}
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐