洛谷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;
}
posted @ 2025-07-10 17:51  IC0CI  阅读(5)  评论(0)    收藏  举报