1.每次清理车走的路是一个简单环
2.清理完之后环上所有的街道改变状态(脏->不脏,不脏->脏)
3.给出初始状态和终止状态
4.求一个合法的清理车清理方案。
1.如果初始状态与终止状态不一致,这条路就需要被清理
2.只需要存需要清理的边就行了
因为如果存在合法的方案,其中有覆盖不需要清理的边,那么这条边肯定被偶数个环经过,每两个环可以并成一个由全部需要清理的边组成的环
3.整理出边以后,就是找环,找一个每条边刚好被经过一次的环——欧拉回路
欧拉回路的具体操作:
①判连通(这里需要多个回路,所以这步省略)
②判度数,不能存在度数为奇数的点
③一遍搜过去,回溯时存下边
④一路上把经过的边直接标记
⑤最后按一定顺序输出
#include
using namespace std;
typedef pair<int,int>P;
const int M=100005;
int n,m;
int head[M],asdf;
bool mark[M*10],vis[M];
int du[M],que[M*20],len;
vector<P>ans;
struct edge {
int to,nxt,id;
} G[M*20];
void add_edge(int a,int b,int c) {
G[++asdf].to=b;
G[asdf].nxt=head[a];
G[asdf].id=c;
head[a]=asdf;
}
void dfs(int x) {
vis[x]=1;
for(int &i=head[x]; i; i=G[i].nxt) {
if(mark[G[i].id])continue;
int y=G[i].to;
mark[G[i].id]=1;
dfs(y);
ans.push_back(P(x,y));
}
}
int stk[M],top;
int cnt[M],po[M*100];
int main() {
int a,b,x,y;
scanf("%d %d",&n,&m);
for(int i=1; i<=m; i++) {
scanf("%d %d %d %d",&a,&b,&x,&y);
if(x==y)continue;
add_edge(a,b,i);
add_edge(b,a,i);
du[a]++,du[b]++;
que[++len]=a,que[++len]=b;
}
sort(que+1,que+1+len);
len=unique(que+1,que+1+len)-que-1;
bool flag=1;
for(int i=1; i<=len; i++) {
if(du[que[i]]&1)flag=0;
}
if(!flag)printf("NIE\n");
else {
for(int i=1; i<=len; i++) {
if(!vis[que[i]]) {
dfs(que[i]);
}
}
int sum=0;
top=0;
memset(cnt,0,sizeof(cnt));
for(int i=ans.size()-1; i>=0; i--) {
x=ans[i].first;
if(!cnt[x])stk[++top]=x,cnt[x]++;
y=ans[i].second;
cnt[y]++;
if(cnt[y]==2) {
cnt[y]--;
sum++;
po[sum]=1;
while(stk[top]!=y)cnt[stk[top--]]--,po[sum]++;
} else stk[++top]=y;
}
printf("%d\n",sum);
top=0;
memset(cnt,0,sizeof(cnt));
sum=0;
for(int i=ans.size()-1; i>=0; i--) {
x=ans[i].first;
if(!cnt[x])stk[++top]=x,cnt[x]++;
y=ans[i].second;
cnt[y]++;
if(cnt[y]==2) {
cnt[y]--;
sum++;
printf("%d ",po[sum]);
printf("%d ",y);
while(stk[top]!=y) {
printf("%d ",stk[top]);
cnt[stk[top--]]--;
}
printf("%d\n",y);
} else stk[++top]=y;
}
}
return 0;
}