转移方程:

附上代码:
#include<bits/stdc++.h>
#define int long long
#define pii pair<int,int>
using namespace std;
const int N=5e5+5,M=1e6+5,mod=1e9+7;
int n,m,l,colnum,tot;
int dfn[N],low[N],vis[N],s[N],num[N],ednum[N],lg[N+M],dp[N][2][2],cnt[N][2],col[N];
pii edge[M];
vector<pii>b[N];
vector<int>tr[N];
void tarjan(int x,int f){
dfn[x]=low[x]=++tot;
vis[x]=1;
s[++l]=x;
for(pii i:b[x]){
int v=i.first;
if(i.second==f) continue;
if(!dfn[v]) tarjan(v,i.second);
if(vis[v]) low[x]=min(low[x],low[v]);
}
if(dfn[x]<=low[x]){
colnum++;
while(s[l]!=x){
col[s[l]]=colnum;
num[colnum]++;
vis[s[l]]=0;
l--;
}
col[s[l]]=colnum;
num[colnum]++;
vis[s[l]]=0;
l--;
}
}
void dfs(int x,int f){
bool son=1;
for(int i:tr[x]){
if(i==f) continue;
son=0;
dfs(i,x);
dp[x][0][1]+=dp[i][0][1]*2ll%mod*cnt[x][0]%mod;
dp[x][1][1]+=dp[i][0][1]*2ll%mod*cnt[x][1]%mod+dp[i][1][1]*cnt[x][0]%mod+dp[i][1][1]%mod*cnt[x][1]%mod;
dp[x][1][0]+=dp[i][0][1]*2ll%mod*cnt[x][1]%mod+dp[i][1][1]*cnt[x][1]%mod+dp[i][1][0]*2ll%mod*cnt[x][0]%mod;
dp[x][1][0]%=mod;
dp[x][0][1]%=mod;
dp[x][1][1]%=mod;
}
if(son){
dp[x][0][1]=cnt[x][0];
dp[x][1][1]=dp[x][1][0]=cnt[x][1];
}
}
signed main(){
scanf("%lld%lld",&n,&m);
lg[0]=1;
for(int i=1;i<=n+m;i++){
lg[i]=lg[i-1]*2%mod;
}
for(int i=1;i<=m;i++){
int u,v;
scanf("%lld%lld",&u,&v);
b[u].push_back({v,i});
b[v].push_back({u,i});
edge[i]={u,v};
}
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i,0);
}
for(int i=1;i<=m;i++){
int u=edge[i].first,v=edge[i].second;
if(col[u]==col[v]) ednum[col[u]]++;
else{
tr[col[u]].push_back(col[v]);
tr[col[v]].push_back(col[u]);
}
}
// printf("%d\n",colnum);
// for(int i=1;i<=colnum;i++){
// printf("%d %d\n",num[i],ednum[i]);
// }
for(int i=1;i<=colnum;i++){
cnt[i][0]=lg[ednum[i]];
cnt[i][1]=((lg[num[i]]-1+mod)%mod*lg[ednum[i]])%mod;
}
dfs(1,0);
printf("%lld",dp[1][1][0]);
return 0;
}