Luogu P6815 [PA2009] Cakes 题解

P6815 [PA2009] Cakes

三元环计数题。

无向图三元环计数分为三步:

1 :给所有无向边重定向。记录每个点的度数,度数大的点指向度数小的点。如果度数相同,编号小的点指向编号大的点。最后这个图是有向无环图。

2 :打标记。对于图中每一个点 u,将其相邻的点标记可以被 u 到达。

3 :统计答案。对于图中每一个点 u,遍历其可以相邻的点 v,如果 v 相邻的点 w 被标记可以被 u 到达,那么 (u,v,w) 构成一个三元环。三元环不会被重复计算。

在这一题中,我们只需要对无向图三元环计数算法的第三步略微改动,当我们发现 (u,v,w) 构成一个三元环时,将答案增加 max(au,av,aw) 即可。

由于无向图三元环计数算法复杂度为 O(mm),所以这个算法的时间复杂度为 O(mm)

本题卡邻接表的常数,注意常数影响。

#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;
}
posted @   w9095  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示