题解:P10996 【MX-J3-T3】Tuple
C. Tuple 官方题解
本题考察的主要知识点:
- 【1】枚举法
- (yummy 做法)【4】vector
- (yummy 做法)【4】指针
暴力做法
20 分
枚举四个点
时间复杂度 vector、set 还是 unordered_set 存储所有的边。后两者不在 J 组考纲内,所以有一个办法使用 bool 数组解决。
如果我们开一个数组 bool *ex[2005][2005];,然后某条 ex[a][b] 已经存在就把 ex[b][c][a] 设成 new 一个。
这样一共只有 bool[2005] 真实存在,空间复杂度
32 分
枚举两条边
正解
yummy 法
和 32 分类似的做法,但是优化枚举
记录 vector。
四重循环,外两层循环枚举
虽然看上去有四重循环,但是事实上每个三元组最多和
#include<bits/stdc++.h>
using namespace std;
int n,m,cnt=0;
vector<int> eg[2005][2005];
bool *ex[2005][2005];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
eg[u][v].emplace_back(w);
if(ex[v][w]==nullptr){
ex[v][w]=new bool[2005];
memset(ex[v][w],0,2005);
}
ex[v][w][u]=1;
}
for(int a=1;a<n;a++)
for(int b=a+1;b<=n;b++){
sort(eg[a][b].begin(),eg[a][b].end());
for(int cc=0;cc<eg[a][b].size();cc++)
for(int dd=cc+1;dd<eg[a][b].size();dd++){
int c=eg[a][b][cc],d=eg[a][b][dd];
if(ex[c][d]!=nullptr && ex[c][d][a] && ex[c][d][b])
cnt++;
}
}
cout<<cnt<<endl;
return 0;
}
EA 法
然而事实上不需要这么麻烦。
考虑先枚举
时间复杂度
#include<bits/stdc++.h>
using namespace std;
int n,m,u[50005],v[50005],w[50005],cnt=0;
bool c[2005][2005];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&u[i],&v[i],&w[i]);
for(int a=1;a<=n;a++){
for(int i=1;i<=m;i++)
if(u[i]==a)
c[v[i]][w[i]]=1;
for(int i=1;i<=m;i++)
if(c[u[i]][v[i]] && c[v[i]][w[i]] && c[u[i]][w[i]])
cnt++;
for(int i=1;i<=m;i++)
if(u[i]==a)
c[v[i]][w[i]]=0;
}
cout<<cnt;
return 0;
}