0%

Codeforces gym 102860I. Walk of Three 题解

题解

注意到,题目中仅需要走三步,要求是不可以走重复的路以及不可以回到 \(1\),由于步数很小,我们直接计算方案数:首先我们把和 \(1\) 相邻的点标记出来,之后遍历所有的点,统计其周围有多少个和 \(1\) 直接相连的点,假设对 \(i\) 来说是 \(\text{cnt}[i]\),则后两步可以看做从某一个入边进来,之后选一个不一样的再出去,刚好为 \(3\) 步:即 \[ \text{cnt}[i]\times(\text{cnt}[i]-1) \]

每个点的方案(除了 \(1\))累加即可。(边用链表存会 TLE,换成 vector 存就不会,非常离谱)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// https://codeforces.com/gym/102860/problem/I
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cassert>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;

template <typename _Tp>
void read(_Tp &a, char c = 0, int f = 1) {
for(c = getchar(); !isdigit(c); c = getchar()) if(c == '-') f = -1;
for(a = 0; isdigit(c); a = a * 10 + c - '0', c = getchar()); a *= f;
}

template <typename _Tp>
void write(_Tp a) {
if(a < 0) putchar('-'), a = -a;
if(a > 9) write(a / 10); putchar(a % 10 + '0');
}

const int N = 1e5 + 5;
const int M = 2 * N;

int n, m;

vector<int> to[N];

bool t1[N];
int cnt[N];

int main() {
// freopen("0731_1.in", "r", stdin);
read(n), read(m);
while(m--) {
int u, v;
read(u), read(v);
to[u].push_back(v);
to[v].push_back(u);
}
for(auto x : to[1]) {
t1[x] = 1;
}
for(int u = 1; u <= n; u++) {
if(t1[u]) {
for(auto v : to[u]) {
cnt[v]++;
}
}
}
ll ans = 0;
for(int i = 2; i <= n; i++) {
if(cnt[i] > 1) ans += cnt[i] * (cnt[i] - 1);
}
write(ans), putchar('\n');
return 0;
}