P9923 [POI 2023/2024 R1] Przyciski

思路

首先看到 01 矩阵,还是关于行和列的计算,考虑从每个点的行向这个点的列连边。
容易发现这是一个二分图,但是其实没什么用(行与行,列与列之间显然无法连边)。
最后我们要使每个点的度数相同。
首先考虑偶数情况,是容易的,选出一个环,环上的点均度数为 $2$,不在环上的点度数均为 $0$ 即可构造。
这一部分直接 dfs 即可。
然后是奇数情况。
首先若有环,则偶数情况成立,不会考虑,故此时图上无环,是一个森林。
我们发现叶子的度数均为 $1$,无法增加到更大的奇数,所以考虑从叶子到根枚举,若其父亲度数为偶数则断掉父亲到父亲的父亲的连边(不能断掉其与儿子的连边,否则儿子的度数会变为偶数),若父亲为根节点且度数为偶数,则不成立。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include<bits/stdc++.h>
#define fir first
#define sec second
#define int long long
#define pii pair<int,int>
#define fep(i,s,e) for(int i=s;i<e;i++)
#define pef(i,s,e) for(int i=s;i>e;i--)
#define rep(i,s,e) for(int i=s;i<=e;i++)
#define per(i,s,e) for(int i=s;i>=e;i--)
namespace FastIO{
template<typename T>inline void read(T &x){
x=0;int f=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);x*=f;
}
template<typename T,typename...Args>
inline void read(T &x,Args&...args){
read(x);
read(args...);
}
template<typename T>void print(T x){
if(x<0)x=-x,putchar('-');
if(x>9)print(x/10);
putchar((x%10)^48);
}
}
using namespace std;
using namespace FastIO;
const int N=1e5+7;
int n,m;
vector<pii>G[N<<1];
bool vis[N<<1];
bool choose[N*5];
int deg[N<<1];
int st,ed,nxt[N<<1],id[N<<1];
void dfs(int u,int fa){
vis[u]=1;
for(auto i:G[u]){
int v=i.fir;
int w=i.sec;
if(v==fa)continue;
nxt[u]=v;
id[u]=w;
if(vis[v]){
st=v; ed=u;
return;
}
dfs(v,u);
if(st)return;
}
}
bool dfs_odd(int u,int f){
vis[u]=1;
int cnt=0;
for(auto i:G[u]){
int v=i.fir;
int w=i.sec;
if(v==f||vis[v])continue;
if(dfs_odd(v,u)){
choose[w]=1;
cnt++;
}
}
return (cnt%2==0);
}
signed main(){
read(n,m);
rep(i,1,m){
int u,v;
read(u,v);
v+=n;
G[u].emplace_back(v,i);
G[v].emplace_back(u,i);
}
rep(i,1,n){
if(!vis[i]){
dfs(i,0);
if(st){
vector<int> ans;
int u=st;
while(true){
ans.push_back(id[u]);
u=nxt[u];
if(u==nxt[ed])break;
}
puts("TAK");
print(ans.size());
putchar('\n');
for(int x:ans){
print(x);
putchar(' ');
}
return 0;
}
}
}
memset(vis,0,sizeof vis);
rep(i,1,n){
if(!vis[i]){
if(dfs_odd(i,0)){
puts("NIE");
return 0;
}
}
}
vector<int>ans;
rep(i,1,m)if(choose[i])ans.push_back(i);
if(ans.empty()){
puts("NIE");
return 0;
}
puts("TAK");
print(ans.size());
putchar('\n');
for(int x:ans){
print(x);
putchar(' ');
}
}