zoukankan      html  css  js  c++  java
  • 【BZOJ3498】[PA2009] Cakes(某黑科技)

    点此看题面

    大致题意: 对于所有三元环,求三个顶点的最大权值之和。

    黑科技——三元环

    印象里这个黑科技好像在谁讲课的时候介绍过,是个很巧妙但不常见的技巧。

    考虑如何高效且不重不漏地枚举三元环。

    我们统计每个点的度数,然后人为给无向边定向,从度数小的点向度数大的点连边(度数相同时从编号小向编号大连边)。

    这样一来第一个好处就是,一张无向图被我们转化为了(DAG)

    求解时,我们枚举每一个点(i),然后枚举每一个它连向的点(j)打上标记。接着再次枚举每一个它连向的点(j),并继续枚举(j)连向的点(k),如果(k)被打了标记,则((i,j,k))必然是一个三元环。

    正确性应该比较显然,复杂度证明可以用根号思想:

    • 如果(deg_ilesqrt m),复杂度显然是(O(sqrt m))的。
    • 如果(deg_i>sqrt m),由于它连向的点度数一定大于(deg_i),也就大于(sqrt m),最多只有(sqrt m)个,复杂度也是(O(sqrt m))

    因此总复杂度(O(msqrt m))

    此题做法

    根据上面的黑科技,直接枚举每一个三元环,统计答案即可。

    这题应该可以算是这种黑科技的板子题?

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define M 250000
    #define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
    using namespace std;
    int n,m,a[N+5],d[N+5],f[N+5],x[M+5],y[M+5],ee,lnk[N+5];struct edge {int to,nxt;}e[2*M+5];
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define D isdigit(c=tc())
    		char c,*A,*B,FI[FS];
    	public:
    		I FastIO() {A=B=FI;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
    		Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    }F;
    int main()
    {
    	RI i,j,k;for(F.read(n,m),i=1;i<=n;++i) F.read(a[i]);
    	for(i=1;i<=m;++i) F.read(x[i],y[i]),++d[x[i]],++d[y[i]];//计算度数
    	for(i=1;i<=m;++i) (d[x[i]]^d[y[i]]?d[x[i]]<d[y[i]]:x[i]<y[i])?add(x[i],y[i]):add(y[i],x[i]);//人为定向
    	long long ans=0;for(i=1;i<=n;++i)//枚举点
    	{
    		for(j=lnk[i];j;j=e[j].nxt) f[e[j].to]=i;//打标记
    		for(j=lnk[i];j;j=e[j].nxt) for(k=lnk[e[j].to];k;k=e[k].nxt)//枚举再枚举
    			f[e[k].to]==i&&(ans+=max(a[i],max(a[e[j].to],a[e[k].to])));//找到三元环计算贡献
    	}return printf("%lld",ans),0;
    }
    
  • 相关阅读:
    [OI学习笔记]排列组合&二项式定理
    [OI学习笔记]拓补排序
    [OI学习笔记]DAG最短路的四种算法整理-floyd,Dijkstra,Bellman-Ford,SPFA
    [OI学习笔记]从蒟蒻的角度理解动态规划(DP)——从暴力搜索到动态规划
    [OI学习笔记]最小生成树之Kruskal算法
    [OI学习笔记]最小生成树之Prim算法
    [OI学习笔记]图的存储与遍历-邻接矩阵&邻接表
    将数组中第n个元素,放到第m个元素后面
    Unity3D中播放序列帧动画
    UVA1589 Xiangqi
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ3498.html
Copyright © 2011-2022 走看看