The meaning of problems
Is given by \ (n-\) points \ (m \) no edges connected graph composition, to ensure that no heavy edges and loopback.
You need to find out all the edges, these edges meet exactly exist in a simple ring. A ring is known as a simple ring, if and only if
all the points that it contains only the elapsed time in this loop.
These edges may have noticed a lot of pieces, you just need the output of XOR and their number can be.
Thinking
The spanning tree can start dfs FIG
understood any of a simple ring must contain a non-tree edge
playing examples can be found, if an edge is present in a simple loop, if and only if it satisfies one of the following two conditions :
- This non-edge side of the tree, and it does not cover the side of the tree, and any other non-tree edge side of the tree covered with a common edge
- This side is the side of the tree, and its non-covered side of the tree satisfies the above conditions
So we can add to each non-chain side of the tree-covered side of the tree, the addition was complete enumeration of each non-tree edge statistical answer
Implementation
Can be calculated using a tree difference ideological side of each side of the tree is covered with how many non-tree, we call it \ (val [i] \)
If this non-covered tree tree side edge \ (val [i] \) are \ (1 \) , you can accumulate
it and how to determine the cumulative? Can be done with the prefix (see specific code)
(there is a mysterious skin properties: point on the ring to form a chain spanning tree, so do not seek \ (LCA \) )
Precautions
- Build two-way side
- Note the order, not with a simple ring plus twice
I do not know why, always pay up \ (RE \)
finally can not stand hanging open
int size=40<<20;//40M
__asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));//网站开栈
Also found an interesting thing: general questions about the ring should be built out of the tree and then consider the relationship side of the tree and non-tree edge
code
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+50000;
int n,m,tot,ans;
int fi[N],ne[N<<1],to[N<<1],w[N<<1];
int val[N],dep[N],s[N],asd[N];
bool pd[N];
inline int read()
{
int s=0,w=1; char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
for(;isdigit(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
return s*w;
}
inline void add(int x,int y,int s)
{
ne[++tot]=fi[x],fi[x]=tot,to[tot]=y,w[tot]=s;
}
void dfs1(int x,int pr)
{
dep[x]=dep[pr]+1;
pd[x]=true;
for(int i=fi[x];i;i=ne[i])
{
int v=to[i];
if(v==pr) continue;
if(pd[v])
{
if(dep[v]>dep[x]) continue;//顺序问题
++val[x],--val[v];
continue;
}
dfs1(v,x);
}
}
void dfs2(int x,int pr)
{
pd[x]=true;
for(int i=fi[x];i;i=ne[i])
{
int v=to[i];
if(v==pr||pd[v]) continue;
asd[v]=asd[x]^w[i];
dfs2(v,x);
val[x]+=val[v];
}
}
void dfs3(int x,int pr)
{
pd[x]=true;s[x]=s[pr]+val[x];
for(int i=fi[x];i;i=ne[i])
{
int v=to[i];
if(v==pr) continue;
if(pd[v])
{
if(dep[v]>dep[x]) continue;
if((dep[x]-dep[v])==(s[x]-s[v]))
ans^=asd[x]^asd[v]^w[i];
continue;
}
dfs3(v,x);
}
}
int main()
{
int size=40<<20;//40M
__asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));
n=read(),m=read();
for(int i=1;i<=m;++i)
{
int a=read(),b=read();
add(a,b,i);add(b,a,i);
}
dfs1(1,0);
for(int i=1;i<=n;++i)pd[i]=false;
dfs2(1,0);
for(int i=1;i<=n;++i)pd[i]=false;
dfs3(1,0);
cout<<ans;
exit(0);
}