01 矩阵游戏

构造 #POI

对每一行和每一列建一个点

对于每一个开关\((i,j)\)\(i\) 行向 \(j\) 列建边

问题转化为选择一些边 使得每个点的度的奇偶性相同

分类讨论

  • 如果存在环 那么只选择这个环就可以满足条件 暴搜
  • 否则原图不 存在度数全为偶数的解 并且为一个森林 所以叶子节点必定选中 上面的每条边的状态也是确定的 判合法性即可
// Author: xiaruize
#define ONLINE_JUDGE
#ifndef ONLINE_JUDGE
#define debug(x) cerr << "On Line:" << __LINE__ << #x << "=" << x << endl
bool start_of_memory_use;
#else
#define debug(x)
#endif
#include <bits/stdc++.h>
namespace __DEBUG_UTIL
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1000000007;
const int N = 2e5 + 10;
const int M = 5e5 + 10;

int n, m;
vector<pii> g[N];
pii eg[M];
bool vis[N];
pii fr[N];

void dfs(int x, int fa)
{
    if (vis[x])
    {
        vector<int> res;
        int cur = fr[x].first;
        res.push_back(fr[x].second);
        while (cur != x)
        {
            res.push_back(fr[cur].second);
            cur = fr[cur].first;
        }
        cout << "TAK\n";
        cout << res.size() << "\n";
        for (auto v : res)
            cout << v << ' ';
        exit(0);
    }
    vis[x] = true;
    for (auto [v, id] : g[x])
    {
        if (v == fa)
            continue;
        fr[v] = {x, id};
        dfs(v, x);
    }
}

vector<int> res;

bool calc(int x, int fa, int id)
{
    vis[x] = true;
    if (g[x].size() == 1 && x != fa)
    {
        res.push_back(id);
        return true;
    }
    bool cur = false;
    for (auto [v, cid] : g[x])
    {
        if (v == fa)
            continue;
        bool tmp = calc(v, x, cid);
        cur ^= tmp;
        debug(v, tmp);
    }
    if (cur)
        return false;
    res.push_back(id);
    return true;
}

void solve()
{
    cin >> n >> m;
    rep(i, 1, m)
    {
        int u, v;
        cin >> u >> v;
        v += n;
        g[u].push_back({v, i});
        g[v].push_back({u, i});
        eg[i] = {u, v};
    }
    rep(i, 1, n * 2)
    {
        if (!vis[i])
            dfs(i, 0);
    }
    mms(vis, 0);
    bool fl = false;
    rep(i, 1, n * 2) if (!vis[i])
    {
        fl |= calc(i, i, 0);
        debug(i, fl);
    }
    if (fl)
    {
        cout << "NIE\n";
        return;
    }
    cout << "TAK\n";
    cout << res.size() << "\n";
    for (auto v : res)
        cout << v << ' ';
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
    freopen("matrix.in", "r", stdin);
    freopen("matrix.out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int testcase = 1;
    // cin >> testcase;
    while (testcase--)
        solve();
#ifndef ONLINE_JUDGE
    cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
    cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
    return 0;
}
posted @ 2024-04-15 19:40  xiaruize  阅读(9)  评论(0)    收藏  举报