洛谷P6815 [PA 2009] Cakes
题面分析
给出一个无向图,统计三元环。
一个根号算法(人类智慧?)。
对于所有给出的无向边,我们给他们钦定一个方向,即由入度较大的指向入度较小的,若入度相同就由顶点编号大的指向编号较小的。
这样可以使这个图变成一个有向无环图,其中所有三元环都长这样:

可以使统计复杂度变为 \(O(N \times \sqrt N)\)
关于具体实现
对于一个点,遍历一遍并标记它指向的节点。再遍历它指向的节点指向的节点,若这个点被标记,则有一个三元环,更新答案即可。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int rd()//快读
const int N = 1e5 + 5;
int n,m,a[N],d[N],ans;
vector<int> adj[N];
bool vis[N];
struct E
{
int u,v;
}e[N << 2];
signed main()
{
n = rd(),m = rd();
for(int i = 1;i <= n;i++) a[i] = rd();
for(int i = 1;i <= m;i++) d[e[i].u = rd()]++,d[e[i].v = rd()]++;
for(int i = 1;i <= m;i++)
{
auto [u,v] = e[i];
if(d[u] < d[v] || (d[u] == d[v] && u > v)) swap(u,v);
adj[u].emplace_back(v);
}
for(int i = 1;i <= n;i++)
{
for(auto u : adj[i]) vis[u] = 1;
for(auto u : adj[i]) for(auto v : adj[u]) if(vis[v]) ans += max({a[i],a[u],a[v]});
for(auto u : adj[i]) vis[u] = 0;
}
cout << ans;
return 0;
}

浙公网安备 33010602011771号