Luogu P6815 [PA2009] Cakes 题解
三元环计数题。
无向图三元环计数分为三步:
:给所有无向边重定向。记录每个点的度数,度数大的点指向度数小的点。如果度数相同,编号小的点指向编号大的点。最后这个图是有向无环图。
:打标记。对于图中每一个点 ,将其相邻的点标记可以被 到达。
:统计答案。对于图中每一个点 ,遍历其可以相邻的点 ,如果 相邻的点 被标记可以被 到达,那么 构成一个三元环。三元环不会被重复计算。
在这一题中,我们只需要对无向图三元环计数算法的第三步略微改动,当我们发现 构成一个三元环时,将答案增加 即可。
由于无向图三元环计数算法复杂度为 ,所以这个算法的时间复杂度为 。
本题卡邻接表的常数,注意常数影响。
#include <bits/stdc++.h>
using namespace std;
struct edge
{
int v,nxt;
}e[600000];
int n,m,a[200000],h[200000],b[200000],ind[200000],u[400000],v[400000],cnt=0;
long long ans=0;
void add_edge(int u,int v)
{
e[++cnt].nxt=h[u];
e[cnt].v=v;
h[u]=cnt;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=m;i++)u[i]=read(),v[i]=read(),ind[u[i]]++,ind[v[i]]++;
for(int i=1;i<=m;i++)
if((ind[u[i]]>ind[v[i]])||(ind[u[i]]==ind[v[i]]&&u[i]<v[i]))add_edge(u[i],v[i]);
else add_edge(v[i],u[i]);
for(int i=1;i<=n;i++)
{
for(int j=h[i];j;j=e[j].nxt)b[e[j].v]=i;
for(int j=h[i];j;j=e[j].nxt)
{
int ad=max(a[i],a[e[j].v]);
for(int k=h[e[j].v];k;k=e[k].nxt)
if(b[e[k].v]==i)ans+=max(ad,a[e[k].v]);
}
}
printf("%lld",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探