Submission #469104

#TimeUsernameProblemLanguageResultExecution timeMemory
469104sinamhdvSubtree (INOI20_subtree)C++11
100 / 100
181 ms27740 KiB
// INOI20_subtree
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod = 1000 * 1000 * 1000 + 7;
const int INF = 1e9 + 100;
const ll LINF = 1e18 + 100;

#ifdef DEBUG
#define dbg(x) cout << #x << " = " << (x) << endl << flush;
#define dbgr(s, f) { cout << #s << ": "; for (auto _ = (s); _ != (f); _++) cout << *_ << ' '; cout << endl << flush; }
#else
#define dbg(x) ;
#define dbgr(s, f) ;
#endif
#define fast_io ios::sync_with_stdio(0); cin.tie(0);
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define fr first
#define sc second
#define endl '\n'

const int MAXN = 100100;
const int MAXE = 150100;

int n, m;
vector<int> adj[MAXN];
int ef[MAXE], eto[MAXE];
int hei[MAXN];
bool iscut[MAXE];
bool mark[MAXN];
vector<int> comp[MAXN];
int cn, cnum[MAXN];
vector<int> tree[MAXN];
int head[MAXN], vpar[MAXN];
int dp[MAXN][2];
int wei[MAXN];

inline void addedge(int x, int y)
{
	tree[x].pb(y);
	tree[y].pb(x);
}

inline int dfs1(int v, int epar)
{
	mark[v] = true;
	int dp = hei[v];
	for (int e : adj[v]) if (e != epar)
	{
		int u = eto[e] ^ ef[e] ^ v;
		if (mark[u]) dp = min(dp, hei[u]);
		else hei[u] = hei[v] + 1, dp = min(dp, dfs1(u, e));
	}
	if (dp >= hei[v] && epar >= 0) iscut[epar] = true;
	return dp;
}

void dfs2(int v)
{
	cnum[v] = cn;
	comp[cn].pb(v);
	for (int e : adj[v]) if (!iscut[e])
	{
		int u = ef[e] ^ eto[e] ^ v;
		if (!cnum[u]) dfs2(u);
	}
}

void dfs3(int v)
{
	mark[v] = true;
	for (int e : adj[v])
	{
		int u = ef[e] ^ eto[e] ^ v;
		if (mark[u]) continue;
		if (iscut[e])
		{
			head[cnum[u]] = u;
			vpar[cnum[u]] = v;
		}
		dfs3(u);
	}
}

void dfs4(int v, int par)
{
	for (int u : tree[v]) if (u != par)
	{
		dfs4(u, v);
		wei[vpar[u]] = (wei[vpar[u]] * ((ll)dp[u][1] + 1)) % mod;
	}

	// calc dp
	if ((int)comp[v].size() == 1)	// single vertex
	{
		dp[v][0] = dp[v][1] = wei[comp[v][0]];
		return;
	}
	
	// cycle
	int k = (int)comp[v].size();
	vector<int> ps(k + 5);
	
	ps[0] = 0;
	int cur = 1;
	FOR(i, 1, k + 1)
	{
		cur = (ll)cur * wei[comp[v][i - 1]] % mod;
		ps[i] = (ps[i - 1] + cur) % mod;
	}

	dbgr(ps.begin(), ps.end());

	cur = 1;
	for (int i = k - 1; i >= 1; i--)
	{
		dp[v][1] = (dp[v][1] + (ll)ps[i] * cur) % mod;
		cur = (ll)cur * wei[comp[v][i]] % mod;
	}

	dp[v][0] = dp[v][1];
	cur = 0;
	FOR(i, 1, k)
	{
		cur = wei[comp[v][i]] * ((ll)cur + 1) % mod;
		dp[v][0] = (dp[v][0] + cur) % mod;
	}
}

int32_t main(void)
{
	fast_io;
	cin >> n >> m;
	FOR(i, 0, m)
	{
		cin >> ef[i] >> eto[i];
		adj[ef[i]].pb(i);
		adj[eto[i]].pb(i);
	}

	dfs1(1, -1);
	
	dbgr(iscut, iscut + m);

	FOR(i, 1, n + 1) if (!cnum[i]) cn++, dfs2(i);

	memset(mark, 0, sizeof(mark));
	dfs3(1);
	head[cnum[1]] = 1;

	FOR(i, 0, m) if (iscut[i]) addedge(cnum[ef[i]], cnum[eto[i]]);

	FOR(i, 1, cn + 1)
	{
		rotate(comp[i].begin(), find(all(comp[i]), head[i]), comp[i].end());
	}

	dbg(cn);
	FOR(i, 1, cn + 1)
	{
		dbg(i);
		dbg(head[i]);
		dbg(vpar[i]);
		dbgr(comp[i].begin(), comp[i].end());
	}

	fill(wei + 1, wei + n + 1, 1);
	dfs4(cnum[1], -1);

#ifdef DEBUG
	dbgr(wei + 1, wei + n + 1);
	FOR(i, 1, cn + 1) cout << "(" << dp[i][0] << ", " << dp[i][1] << ") ";
	cout << endl;
#endif

	ll ans = 0;
	FOR(i, 1, cn + 1) ans = (ans + dp[i][0]) % mod;
	ans = (mod + ans % mod) % mod;
	cout << ans << endl;

	return 0;
}


#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...