通过题目可以看到,每个点 的度数都是小于3的,而且每个点只可能最多属于一个简单环,所以我们可以考虑用dfs 找到每一个环然后将每个环缩减成为一个点再将其和原来的边进行重新连边
然后我们就可以发现,建完新图之后的题目就简化成了一棵树
然后又可以发现一条性质:
两个简单环之间的路径数目就是就是 两个简单环之间个数的2k,因为每一个路径都可以分为上下两种走法
之后就进行树形DP
f
[
x
]
表
示
以
x
点
位
节
点
的
半
个
眼
镜
有
多
少
个
f[x]表示以x点位节点的半个眼镜有多少个
f[x]表示以x点位节点的半个眼镜有多少个
当这个第是一个简单环的时候,就可以从这个点走到儿子结点,可以构成两倍的半个眼镜
f
[
x
]
=
f
[
x
]
+
f
[
y
]
∗
2
;
f[x]=f[x]+f[y]*2;
f[x]=f[x]+f[y]∗2;
当这个第是一个普通点的时候,就只有儿子走到自己 f [ x ] = f [ x ] + f [ y ] ; f[x]=f[x]+f[y]; f[x]=f[x]+f[y];
a
n
s
[
x
]
表
示
x
为
节
点
的
手
铐
数
,
y
是
子
节
点
ans[x]表示x为节点的手铐数,y是子节点
ans[x]表示x为节点的手铐数,y是子节点
计算答案就是将半个眼镜 乘在一起构成整个眼镜
a
n
s
[
x
]
=
a
n
s
[
x
]
+
f
[
x
]
∗
f
[
y
]
+
a
n
s
[
y
]
;
ans[x]=ans[x]+f[x]*f[y]+ans[y];
ans[x]=ans[x]+f[x]∗f[y]+ans[y];
#include<bits/stdc++.h>
#define maxn 2000010
#define mod 19260817
#define int long long
using namespace std;
inline int read()
{
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch)){res=(res<<1)+(res<<3)+(ch&15);ch=getchar();}
return res*f;
}
int n,m;
int vis[maxn];
int num[maxn],numal;
int pr[maxn];
int dp[maxn];
int zs[maxn];
int ans[maxn];
int tot,head[maxn];
struct node{
int to,ne;
}edge[maxn*2];
inline void add(int x,int y)
{
edge[++tot].to=y;
edge[tot].ne=head[x];
head[x]=tot;
}
inline void dfs(int x,int fa)
{
if(vis[x]==2)return;
if(vis[x]==1)
{
int k=pr[x];
num[++numal]=1;
zs[x]=numal;
vis[x]=2;
while(k!=x)
{
num[numal]++;
zs[k]=numal;
vis[k]=2;
k=pr[k];
}
return;
}
vis[x]=1;
for(int i=head[x];i;i=edge[i].ne)
{
int to=edge[i].to;
if(to==fa)continue;
pr[to]=x;
dfs(to,x);
}
}
int u[maxn],v[maxn];
inline void Dp(int x,int fa)
{
ans[x]=0;
if(num[x]>1)dp[x]=1;
else dp[x]=0;
for(int i=head[x];i;i=edge[i].ne)
{
int to=edge[i].to;
if(to==fa)continue;
Dp(to,x);
ans[x]=(ans[x]+(dp[x]*dp[to])%mod+ans[to])%mod;
if(num[x]>1)dp[x]=(dp[x]+dp[to]*2)%mod;
else dp[x]=(dp[x]+dp[to])%mod;
}
}
signed main()
{
n=read();m=read();
for(int i=1;i<=m;i++)
{
u[i]=read();v[i]=read();
add(u[i],v[i]);add(v[i],u[i]);
}
dfs(1,1);
for(int i=1;i<=n;i++)if(vis[i]!=2)num[++numal]=1,zs[i]=numal;
tot=0;memset(head,0,sizeof(head));
for(int i=1;i<=m;i++)
{
if(zs[u[i]]!=zs[v[i]])
{
add(zs[u[i]],zs[v[i]]);
add(zs[v[i]],zs[u[i]]);
}
}
Dp(1,1);
printf("%d\n",ans[1]);
return 0;
}