Tarjan+DP求调(违规紫杉)
查看原帖
Tarjan+DP求调(违规紫杉)
148552
我很低调楼主2022/11/27 11:09

退役15pts

#include<cstdio>
#include<algorithm>
#define ll long long
#define mod 1000000007ll
using namespace std;
struct node{ll v,nxt;}edge[2000006],tree[2000006];
ll head[500005],cnt=1;
ll thead[500005],tot;
ll n,m;
ll fa[500005],ans;
ll x,y,len;
ll dfn[500005],low[500005],idex;
ll bian1[2000005],bian2[2000005];
bool bd[2000006],vis[500005];
ll dp[500005][3];
ll tou[500005],root;
ll bian[500005],dian[500005];

ll find(ll x){if(fa[x]==x)return x;return (fa[x]=find(fa[x]));}
ll ksm(ll x,ll b);
void adge(ll u,ll v){edge[++cnt]=(node){v,head[u]};head[u]=cnt;}
void lianb(ll u,ll v){tree[++tot]=(node){v,thead[u]};thead[u]=tot;}
void Tarjan(ll u,ll ba){
	low[u]=dfn[u]=++idex;
	for(ll i=head[u],v;i;i=edge[i].nxt){v=edge[i].v;
		if(v==ba)continue;
		if(!dfn[v]){
			Tarjan(v,u);
			if(low[v]>dfn[u])bd[i]=bd[i^1]=1;
			low[u]=min(low[u],low[v]);
		}else low[u]=min(low[u],dfn[v]);
	}
}
void dfs(ll u){
	vis[u]=1;tou[u]=root;dian[root]++;
	for(ll i=head[u],v;i;i=edge[i].nxt){v=edge[i].v;
		if(bd[i]||vis[edge[i].v])continue;
		dfs(v);
	}
}
void tdp(ll u,ll ba){
	ll d=(ksm(2ll,bian[u]+dian[u])-ksm(2ll,bian[u])+mod)%mod;
	dp[u][0]=1ll;dp[u][1]=0;
	for(ll i=thead[u],v;i;i=tree[i].nxt){
		v=tree[i].v;
		if(v==ba)continue;
		tdp(v,u);
		dp[u][1]=(dp[u][0]*dp[v][1]%mod+dp[u][1]*((dp[v][0]+dp[v][1])%mod)%mod)%mod;
		dp[u][0]=((dp[u][0]*2%mod)*dp[v][0])%mod;
	}
	dp[u][1]=(dp[u][0]*d%mod+dp[u][1]*d%mod+dp[u][1]*ksm(2ll,bian[u])*2)%mod;
	dp[u][0]=dp[u][0]*ksm(2ll,bian[u])%mod;
	return;
}
int main(){freopen("barrack.in","r",stdin);freopen("barrack.out","w",stdout);
	scanf("%lld%lld",&n,&m);
	for(ll i=1,u,v;i<=m;i++){
		scanf("%lld%lld",&u,&v);
		adge(u,v);adge(v,u);
		bian1[i]=u;bian2[i]=v;
	}
	Tarjan(1,0);root=0;
	for(ll i=1;i<=n;i++){
		if(vis[i])continue;
		root++;dfs(i);
	}
	for(ll i=1;i<=n;i++)fa[i]=i;
	for(ll i=1,rt1,rt2;i<=m;i++){
		if(tou[bian1[i]]==tou[bian2[i]]){
			bian[tou[bian1[i]]]++;
			continue;
		}
		rt1=find(tou[bian1[i]]);rt2=find(tou[bian2[i]]);
		if(rt1==rt2)continue;
		fa[rt1]=rt2;
		lianb(tou[bian1[i]],tou[bian2[i]]);
		lianb(tou[bian2[i]],tou[bian1[i]]);
	}
	tdp(1,0);
	printf("%lld\n",dp[1][1]);
	return 0;
}
ll ksm(ll x,ll b){
	ll res=1ll;
	while(b){if(b&1ll)res=res*x%mod;x=x*x%mod;b>>=1;}
	return res;
}

2022/11/27 11:09
加载中...