题目
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
vector<int> G[maxn];
int dis[maxn], fa[maxn];
bool isleaf[maxn], vis[maxn];
queue<int> q;
ll res, k;
void bfs()
{ // 构建bfs树
vis[1] = 1;
dis[1] = 0;
q.push(1);
res++;
while (!q.empty())
{
int u = q.front();
q.pop();
for (auto v : G[u])
{
if (vis[v]){
if(dis[v] == dis[u]){//同一层的非树边,会遍历两遍
isleaf[u] = isleaf[v] = 0;//非树边分裂之后,两端的结点不能当作叶结点最后再分裂
res += max(k - dis[u], 0LL);
}
else if(dis[v] == dis[u] + 1){//不同层的非树边,本来会遍历两遍,但是以深的点拓展到浅的点时,无法判断是树边还是非树边
isleaf[u] = isleaf[v] = 0;//同理
res += max(k - dis[u], 0LL) + max(k - dis[v], 0LL);//两边的分裂一起计算,只遍历一次
}
continue;
}
vis[v] = 1;
dis[v] = dis[u] + 1;
if(dis[v] <= k) res++;
//fa[v] = u;
isleaf[u] = 0; // 如果当前节点u更新了其他节点的距离,则当前节点不是叶节点
q.push(v);
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
ll n, m, i, j, u, v, ans = 1;
cin >> n >> m >> k;
for (i = 1; i <= m; i++)
{
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
memset(isleaf, 1, sizeof(isleaf));
memset(dis, 0x3f, sizeof(dis));
bfs();
//法二:bfs时记录每个结点的父结点,最后一起统计
// for (i = 2; i <= n; i++)
// {
// if (dis[i] > k)
// continue; // 距离大于k的节点
// ll cnt = 0;
// for (auto v : G[i])
// {
// if (fa[i] == v || fa[v] == i)
// continue; // 跳过bfs树边
// cnt++; // 非树边++
// }
// if (isleaf[i])
// cnt = max(cnt, 1LL); // 如果是叶结点,可以选择在bfs树边或非树边分裂(取较大者)
// ans += (k - dis[i]) * cnt + 1;
// }
// cout << ans;
for(i = 2; i <= n; i++){
if(isleaf[i] && dis[i] < k){
res += k - dis[i];
}
}
cout << res;
return 0;
}