题目大意:给定n个点m条边,每条边有一个初始权值0或1,有一个最终权值0或1,每次可以给一个简单环上的边权值异或1,求一种方案使得每条边从初始权值变成最终权值
一看这个样子就知道不需要该变的边没啥用,因为反正都要变两次,不如把这两次合起来,然后这些边不变..
然后我就写了一个找欧拉回路的算法,交上去WA了....
然后就要了数据,发现需要特判单独的点,否则会输出一些奇怪的东西....
然后还是WA
TAT||||
为啥题里没说“必须是简单环”啊,这样欧拉回路就不行了....那我们可以维护一个像栈一样的东西遇到一个环就弹出去
再交一发TLE...
然后就想起来毛啸出的那道coloring....也就是邻接表求欧拉回路的时间复杂度会退化到O(N^2)
所以就要用到类似网络流的当前弧优化的东西
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define N 1000010
using namespace std;
int to[N<<1],nxt[N<<1],num[N<<1],pre[N],cnt;
void NO(){puts("NIE");exit(0);}
void ae(int ff,int tt)
{
cnt++;
to[cnt]=tt;
nxt[cnt]=pre[ff];
pre[ff]=cnt;
num[cnt]=(cnt-1)/2;
}
int du[N];
bool used[N],vis[N];
int fark;
void dfs(int x)
{
fark++;
used[x]=true;
int i,j;
for(i=pre[x];i;i=nxt[i])
{
j=to[i];
if(used[j]) continue;
dfs(j);
}
}
vector<int>V[N];
int tot;
bool zai[N];
int s[N],t;
void dfs2(int x)
{
used[x]=true;
if(zai[x])
{
tot++;
V[tot].push_back(x);
while(s[t]!=x)
{
zai[s[t]]=false;
V[tot].push_back(s[t]);
t--;
}
zai[s[t]]=false;
V[tot].push_back(s[t]);
t--;
}
int i,j;
for(i=pre[x];i;i=pre[x])
{
pre[x]=nxt[i];
if(!vis[num[i]])
{
zai[x]=true;
t++;s[t]=x;
vis[num[i]]=true;
dfs2(to[i]);
}
}
}
char ch,B[1<<15],*S=B,*T=B;
#define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?0:*S++)
inline int read()
{
int x=0,f=1;char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
int main()
{
int n,m;
n=read();m=read();
int i,j,x,y,u,v;
while(m--)
{
x=read();y=read();u=read();v=read();
if(u!=v)
{
du[x]++;du[y]++;
ae(x,y),ae(y,x);
}
}
for(i=1;i<=n;i++)
if(du[i]&1) NO();
for(i=1;i<=n;i++)
if(!used[i])
dfs2(i);
printf("%d\n",tot);
for(i=1;i<=tot;i++)
{
printf("%d ",V[i].size()-1);
for(j=0;j<V[i].size();j++)
printf("%d ",V[i][j]);
puts("");
}
}