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;
}