题意:
给出一个n个点m条边无向图,每个边有一个01状态;
现在可以选择一些环,使环上的所有状态取反;
给出初始与结束状态,求一个方案;
1<=n<=100000,1<=m<=1000000;
题解:
做完这题深刻的体会到自己的too young too naive;
首先有一个性质,如果有解,一定存在一种方案使选择的所有环不重复经过一条边;
这个性质也说明了,所有不需要更改的边是可以忽视的;
因为如果将其选了偶数次,也可以构造出另一种方案不选它;
所以问题转化成从原图选出状态不同的边,然后求多个欧拉回路覆盖所有边的方案;
无向图存在欧拉回路的条件是结点的度都是偶数;
判掉NIE的情况之后,开始求图的欧拉回路。。
然后我写个搜索就被卡了!并不是常数的问题而是复杂度不对;
首先大多数人的图都是用链式前向星存对吧;
那么每次搜到一个点遍历一遍边表找没被删除的边的时候。。
这就给了丧心病狂的人可乘之机!
给出一个是:
这个样子的菊花图,5W个褶,然后扫着扫着就超时了;
所以我们要更新前向星中的head[x],每次删除的边都是最上面的,只要将head[x]赋为某个next就行了;
时间复杂度O(n+m),读入较大,输出较大,常数较大;
在连续几道题垫底的节奏下终于有一道题Rank1啦好开心;
代码:
#include<cctype>
#include<vector>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 131072
#define M 2100000
#define LEN 1<<20
using namespace std;
int to[M],next[M],head[N],ce=1;
int du[N];
bool ban[M],vis[N];
int cnt;
char getc()
{
static char *S,*T,buf[LEN];
if(S==T)
{
T=(S=buf)+fread(buf,1,LEN,stdin);
if(S==T)
return EOF;
}
return *S++;
}
int read()
{
static char ch;
static int D;
while(!isdigit(ch=getc()));
for(D=ch-'0';isdigit(ch=getc());)
D=D*10+ch-'0';
return D;
}
namespace ans
{
int val[M],next[M],head[N<<1],size[N<<1],ce;
void add(int x,int y)
{
size[x]++;
val[++ce]=y;
next[ce]=head[x];
head[x]=ce;
}
}
void add(int x,int y)
{
to[++ce]=y;
next[ce]=head[x];
head[x]=ce;
}
int dfs(int x,int pre)
{
vis[x]=1;
int i,y;
for(i=head[x];i;i=next[i])
{
if(ban[i]||(i^1)==pre) continue;
if(!vis[to[i]])
{
y=dfs(to[i],i);
ans::add(cnt,x);
ban[i]=ban[i^1]=1;
head[x]=next[i];
if(x!=y)
{
vis[x]=0;
return y;
}
}
else
{
cnt++;
ans::add(cnt,to[i]);
ans::add(cnt,x);
ban[i]=ban[i^1]=1;
head[x]=next[i];
vis[x]=0;
return to[i];
}
}
vis[x]=0;
return 0;
}
int main()
{
int n,m,i,j,k,x,y,z,w;
n=read(),m=read();
for(i=1;i<=m;i++)
{
x=read(),y=read(),z=read(),w=read();
if(z!=w)
add(x,y),add(y,x),du[x]++,du[y]++;
}
for(i=1;i<=n;i++)
{
if(du[i]&1)
{
puts("NIE");
return 0;
}
}
for(i=1;i<=n;i++)
{
if(head[i])
dfs(i,0);
}
printf("%d\n",cnt);
for(i=1;i<=cnt;i++)
{
printf("%d ",ans::size[i]-1);
for(j=ans::head[i];j;j=ans::next[j])
{
printf("%d ",ans::val[j]);
}
printf("\n");
}
return 0;
}