HDU6184【Counting Stars】(三元环计数)
題面
傳送門
給出一張無向圖,求 \(4\) 個點構(gòu)成兩個有公共邊的三元環(huán)的方案數(shù)。
題解
orz余奶奶,orz zzk
首先,如果我們知道經(jīng)過每條邊的三元環(huán)個數(shù)\(cnt_i\),那么答案就是\(\sum_{i=1}^m{cnt_i\choose 2}\)
所以現(xiàn)在問題就是該怎么數(shù)三元環(huán)
據(jù)說有一個設(shè)閾值的\(O(m\sqrt{m})\)的做法,不過常數(shù)太大了,這里不講
我們把每一條邊重定向,設(shè)它連接的兩個點的度數(shù)分別為\(deg_u\)和\(deg_v\),那么把這條邊定為從度數(shù)大的連向度數(shù)小的,如果度數(shù)相同按標號大小。這樣顯然可以建出一個有向無環(huán)圖
所以怎么找環(huán)呢
我們枚舉點\(u\),并枚舉它的所有出邊,把出邊指向的點\(v\)標記上\(u\)。然后再枚舉一邊出邊,并對每個\(v\)也枚舉出邊,如果\(v\)的出邊指向的點\(w\)上的標記是\(u\)那么說明找到了一個三元環(huán)
顯然,每個三元環(huán)都會被統(tǒng)計恰好一次
接下來的問題是復(fù)雜度,我們要證明它的上界是\(O(m\sqrt{m})\)
1.\(\forall v,out_v\leq \sqrt{m}\),每一次枚舉\(v\)的出邊的復(fù)雜度不會超過\(O(\sqrt{m})\),所以這一部分復(fù)雜度不會超過\(O(m\sqrt{m})\)
2.\(\forall v,out_v\geq \sqrt{m}\),因為在這種情況下必有\(deg_u\geq deg_v\),所以所有這樣的\(u\)不會超過\(O(\sqrt{m})\)個,每一個\(out_v\)的貢獻最多是\(\sqrt{m}out_v\),由于\(\sum out_v=O(m)\),所以這一部分的復(fù)雜度也不會超過\(O(m\sqrt{m})\)
不過這個做法常數(shù)不知道比設(shè)閾值小到哪里去了
//minamoto #include<bits/stdc++.h> #define R register #define ll long long #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) using namespace std; char buf[1<<21],*p1=buf,*p2=buf; inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} int read(){R int res,f=1;R char ch;while((ch=getc())>'9'||ch<'0')if(ch==EOF)return -1;for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');return res*f; } const int N=2e5+5; struct eg{int v,nx;}e[N<<1];int head[N],tot; inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;} struct EG{int u,v;}E[N]; int n,m,tim,deg[N],pt[N],vis[N],cnt[N];ll res; int main(){ // freopen("testdata.in","r",stdin);while(~(n=read(),m=read())){tot=tim=0;fp(i,1,n)head[i]=deg[i]=vis[i]=0;fp(i,1,m)E[i].u=read(),E[i].v=read(),++deg[E[i].u],++deg[E[i].v],cnt[i]=0;fp(i,1,m)deg[E[i].u]>deg[E[i].v]||(deg[E[i].u]==deg[E[i].v]&&E[i].u>E[i].v)?add(E[i].u,E[i].v):add(E[i].v,E[i].u);fp(u,1,n){++tim;go(u)pt[v]=i,vis[v]=tim;for(R int k=head[u];k;k=e[k].nx)go(e[k].v)if(vis[v]==tim)++cnt[i],++cnt[k],++cnt[pt[v]];}res=0;fp(i,1,m)res+=1ll*cnt[i]*(cnt[i]-1)>>1;printf("%lld\n",res);}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/bztMinamoto/p/10582360.html
總結(jié)
以上是生活随笔為你收集整理的HDU6184【Counting Stars】(三元环计数)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 奔驰 CTO 证实:自动驾驶系统 DRI
- 下一篇: UltraSoft