HDU-6736-Forest Program
题意
给你n和点m条边,问你有多少种删边的方法。使其变成没有环的图。
思路
找最小环的数量。可以用点强连通分量搞,也可以dfs,记录dfs序就可以了;
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mx=500100;
const ll mod=998244353;
int dfn[mx];
vector<int> ve[mx];
int n,m;
ll ans;
ll poow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void dfs(int x,int fa){
for(int v:ve[x]){
if(v==fa) continue;
if(!dfn[v]){
dfn[v]=dfn[x]+1;
dfs(v,x);
continue;
}
if(dfn[v]<dfn[x]){
ll len=dfn[x]-dfn[v]+1;
ans=ans*(poow(2,len)-1)%mod;
m-=len;
}
}
}
int main(){
ios::sync_with_stdio(0);
while(cin>>n>>m){
ans=1;
for(int x,y,i=0;i<m;i++){
cin>>x>>y;
ve[x].push_back(y);
ve[y].push_back(x);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
dfn[i]=1;
dfs(i,-1);
}
}
ans=ans*poow(2,m)%mod;
cout<<ans<<"\n";
for(int i=1;i<=n;i++){
dfn[i]=0;
ve[i].clear();
}
}
return 0;
}