#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 998244353;
const ll INF = (1e+18) + 7;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-6;
const ld pi = acos(-1.0);
//typedef vector<vector<ll>> mat;
typedef vector<int> vec;

ll mod_pow(ll a, ll n) {
	ll res = 1;
	while (n) {
		if (n & 1)res = res * a%mod;
		a = a * a%mod; n >>= 1;
	}
	return res;
}


int n;
vector<int> G[1 << 18];

int mostfar(int x) {
	queue<int> q;
	vector<bool> used(n, false);
	used[x] = true; q.push(x);
	int res = x;
	while (!q.empty()) {
		int id = q.front(); q.pop();
		res = id;
		rep(j, G[id].size()) {
			int to = G[id][j];
			if (used[to])continue;
			used[to] = true;
			q.push(to);
		}
	}
	return res;
}

vector<int> make_road(int l, int r) {
	vector<int> res;
	function<bool(int, int)> dfs = [&](int id, int fr)->bool {
		if (id == r) {
			res.push_back(id); return true;
		}
		rep(j, G[id].size()) {
			int to = G[id][j]; if (to == fr)continue;
			if (dfs(to, id)) {
				res.push_back(id); return true;
			}
		}
		return false;
	};
	dfs(l, -1);
	return res;
}

bool onroad[1 << 18];
bool marked[1 << 18];
void mark(int id, int fr, int k, int dep) {
	if (dep == k)marked[id] = true;
	rep(j, G[id].size()) {
		int to = G[id][j];
		if (to == fr)continue;
		mark(to, id, k, dep + 1);
	}
}
using dpval = vector<ll>;

dpval merge(dpval &a, dpval &b) {
	dpval res = { 0,0,0 };
	rep(i, 3) {
		rep(j, 3) {
			if (i == 2 && j == 2) {
				(res[2] += a[2] * b[2]) %= mod;
			}
			else if (i*j == 2) {
				(res[1] += a[i] * b[j]) %= mod;
			}
			else {
				(res[0] += a[i] * b[j]) %= mod;
			}
		}
	}
	return res;
}
void update(dpval &a) {
	dpval nex = { 0,0,0 };
	nex[0] = a[0];
	nex[1] = a[1];
	nex[2] = a[0] * 2 + a[1] * 2 + a[2] * 3; nex[2] %= mod;
	swap(a, nex);
}
dpval dfs(int id, int fr) {
	dpval res = { 0,0,1 };
	if (marked[id])res = { 0,1,0 };
	rep(j, G[id].size()) {
		int to = G[id][j];
		if (to == fr)continue;
		dpval nex = dfs(to, id);
		res = merge(res, nex);
	}
	update(res);
	return res;
}
void solve() {
	cin >> n;
	rep(i, n - 1) {
		int a, b; cin >> a >> b; a--; b--;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	if (n == 2) {
		cout << 1 << endl; return;
	}
	int r = 0;
	int l = mostfar(r);
	r = mostfar(l);
	vector<int> v = make_road(l, r);
	int len = v.size();
	rep(i, len)onroad[v[i]] = true;
	rep(i, len) {
		int r = v[i];
		rep(j, G[r].size()) {
			int to = G[r][j];
			if (!onroad[to]) {
				int m = min(i, len - 1 - i);
				mark(to, r, m, 1);
			}
		}
	}
	marked[v[0]] = marked[v[len - 1]] = true;
	if (len % 2) {
		int m = v[len / 2];
		vector<LP> pv;
		rep(j, G[m].size()) {
			int to = G[m][j];
			dpval nex = dfs(to, m);
			nex[2] -= (nex[0] + nex[1]);
			while (nex[2] < 0)nex[2] += mod;
			LP cur = { nex[1],nex[2] };
			pv.push_back(cur);
		}
		ll ans = 0;
		vector<int> zeros;
		rep(i, pv.size()) {
			swap(pv[i].first, pv[i].second);
			//cout << pv[i].first << " " << pv[i].second << endl;
			if (pv[i].first == 0)zeros.push_back(i);
		}
		/*if (zeros.size() >= 3)ans = 0;
		else if (zeros.size() == 2) {
			ans = 1;
			rep(i, pv.size()) {
				if (pv[i].first == 0)ans = ans * pv[i].second%mod;
				else ans = ans * pv[i].first%mod;
			}
		}
		else if (zeros.size() == 1) {
			ll al = 1;
			rep(i, pv.size()) {
				if (pv[i].first > 0)al = al * pv[i].first%mod;
				else al = al * pv[i].second%mod;
			}
			rep(i, pv.size()) {
				if (pv[i].first > 0) {
					ll csum = al * pv[i].second%mod*mod_pow(pv[i].first, mod - 2) % mod;
					ans += csum;
					if (ans >= mod)ans -= mod;
				}
			}
		}*/
		//else {
			vector<ll> rpv(pv.size() + 1);
			rep(i, pv.size()) {
				ll c = pv[i].second*mod_pow(pv[i].first, mod - 2) % mod;
				(rpv[i + 1] += rpv[i] + c) %= mod;
			}
			ll al = 1;
			rep(i, pv.size())al = al * pv[i].first%mod;
			rep(i, pv.size()) {
				ll pre = al * pv[i].second%mod*mod_pow(pv[i].first, mod - 2) % mod;
				ll z = rpv[pv.size()] - rpv[i + 1]; if (z < 0)z += mod;
				pre = pre * z%mod;
				ans += pre; if (ans >= mod)ans -= mod;
			}
		//}
		cout << ans << endl;
	}
	else {
		int m1 = v[len / 2 - 1], m2 = v[len / 2];
		dpval v1 = { 0,0,1 }, v2 = { 0,0,1 };
		rep(j, G[m1].size()) {
			int to = G[m1][j];
			if (to == m2)continue;
			dpval nex = dfs(to, m1);
			v1 = merge(v1, nex);
		}
		rep(j, G[m2].size()) {
			int to = G[m2][j];
			if (to == m1)continue;
			dpval nex = dfs(to, m2);
			v2 = merge(v2, nex);
		}
		ll ans = v1[1] * v2[1] % mod;
		cout << ans << endl;
	}
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(17);
	//init();
	//int t; cin >> t; rep(i, t)solve();
	solve();
	return 0;
}


Measured memory_bytes: 21244