题解:P9923 [POI 2023/2024 R1] Przyciski
前言
不错的二合一题。
思路分析
首先套路地建出二分图:对于 的点,连 的无向边,这样问题转化为选出若干条边,使得所有点的度的奇偶性相同。
发现奇数解和偶数解具有不同的性质,考虑分别处理。
偶数解
图上有环即可。
直接 DFS 找环判断。
奇数解
在没有偶数解的前提下判断。
如果图上没有环,那么图一定是一个森林。
考虑一种经典的处理方式:从叶子往上选边。
具体地,我们从叶子开始选择边,因为叶子只和它的父亲相连,所以这些连接叶子的边一定要选,然后可以把叶子删去,这样有一些父亲就成了新的叶子,继续处理就行。
直接 DFS 处理就行。
如果一个点是根节点,并且它需要和父亲选边,那么一定无解。
把两种情况拼一起就做完了。
注意找环时的细节。
总体复杂度 。
代码实现
写的比较丑。
#include<bits/stdc++.h>
using namespace std;
int n,m,u[500005],v[500005];
int head[200005],nxt[1000005],targetx[1000005],targetw[1000005],tot=1;
void add(int x,int y,int w){
tot++;
nxt[tot]=head[x];
head[x]=tot;
targetx[tot]=y;
targetw[tot]=w;
}
bool vis1[200005],vis2[200005],vis3[1000005],vis4[200005],flag;
stack<int> s;
inline void dfs1(int x,int edge){
if(flag) return;
vis1[x]=vis2[x]=1;
s.push(x);
for(int i=head[x];i;i=nxt[i]){
int y=targetx[i],w=targetw[i];
if(vis3[w]) continue;
if(vis2[y]){
flag=true;
while(s.top()!=y){
vis4[s.top()]=true;
s.pop();
}
vis4[y]=1;
vis3[w]=1;
if(flag){
cout<<"TAK"<<'\n';
int cnt=0;
for(int j=1;j<=m;j++){
if(vis3[j] && vis4[u[j]] && vis4[v[j]+n]){
cnt++;
}
}
cout<<cnt<<'\n';
for(int j=1;j<=m;j++){
if(vis3[j] && vis4[u[j]] && vis4[v[j]+n]){
cout<<j<<' ';
}
}
exit(0);
}
}
if(vis1[y]) continue;
vis3[w]=1;
dfs1(y,w);
vis3[w]=0;
}
vis2[x]=0;
s.pop();
}
int val[200005];
inline void dfs2(int x,int fa,int edge){
vis1[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=targetx[i],w=targetw[i];
if(y==fa) continue;
dfs2(y,x,w);
}
if(!val[x] && !fa){
cout<<"NIE";
exit(0);
}
if(!val[x]){
val[x]^=1;
val[fa]^=1;
vis3[edge]=1;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>u[i]>>v[i];
add(u[i],v[i]+n,i);
add(v[i]+n,u[i],i);
}
for(int i=1;i<=n+n;i++){
if(!vis1[i]){
dfs1(i,0);
}
}
memset(vis3,0,sizeof(vis3));
memset(vis1,0,sizeof(vis1));
for(int i=1;i<=n;i++){
if(!vis1[i]){
dfs2(i,0,0);
}
}
cout<<"TAK"<<'\n';
int cnt=0;
for(int i=1;i<=m;i++){
if(vis3[i]){
cnt++;
}
}
cout<<cnt<<'\n';
for(int i=1;i<=m;i++){
if(vis3[i]){
cout<<i<<' ';
}
}
return 0;
}
本文作者:Kenma
本文链接:https://www.cnblogs.com/Kenma/p/18689769
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步