「NOIP十连赛day1」Tourist Attractions - 定长路径统计 | Bill Yang's Blog
0%

「NOIP十连赛day1」Tourist Attractions - 定长路径统计

题目大意

有多少条简单路径恰好经过了4个点。


初步想法

这种给定长度的题似乎有一种套路:枚举中间点。
枚举中间两个点,尝试统计方案数。
如图:

我们只需要统计以a、b两点延伸出去的点的个数,要求不构成环。
也就是说a、b延伸出去的点没有交集的个数。
似乎还需要一个$O(n)$统计交集,但是我们有一个非常厉害的工具叫做bitset,用它可以在很短时间内统计出交集。
这道题就这么毒瘤的解决了。


代码

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
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
int n;
long long ans=0,Degree[1505];
bitset<1505>state[1505];
vector<int>edges[1505];
void AddEdge(int x,int y) {
edges[x].push_back(y);
Degree[y]++;
}
int main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) {
char x;
cin>>x;
if(x-'0')state[i][j]=1,AddEdge(i,j);
}
for(int Now=1; Now<=n; Now++)
for(int i=0; i<edges[Now].size(); i++) {
int Next=edges[Now][i];
ans+=(Degree[Now]-1)*(Degree[Next]-1)-(state[Now]&state[Next]).count();
}
printf("%lld\n",ans);
return 0;
}
姥爷们赏瓶冰阔落吧~