[JZOJ5037]【NOI2017模拟3.30】轮回
2017-03-30 22:09
459 查看
题目大意
给你n个点,m条边的无向图,求长度为4的环的个数,环要保证4个点都不同。n<=50000,m<=100000
分析
考虑暴力做嘛。枚举一个点,然后让他往外跑2的长度,对于走到一个相同的点x,记次数为cnt[x],答案可以加cnt[x]*(cnt[x]-1)/2。最后答案除4。
怎么暴力才能保证复杂度呢?
考虑一个套路:
有个点i,比它度数大的点最多2m−−−√个。
证明:
设该点有x个度数比他大的点,那么这x个点度数至少为x,那么x*x<=2m,那么x≤2m−−−√
所以对于这道题,我们稍微修改一下暴力就行了。枚举点i,往外跑一长度,遍历到的点再往外走到度数比他大的点,再更新cnt数组来统计答案。为了避免重复,即一种方案被算两次,要求第二次走到的点度数大于i的度数。
做完了。
代码
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; typedef double db; #define fo(i,j,k) for(i=j;i<=k;i++) #define fd(i,j,k) for(i=j;i>=k;i--) const int N=50005,M=200005,G=650; int n,m,i,j,x,y,p; int c ,d ,tow [G],pd ,ref ,f ; int first[M],b[M],next[M],tt; ll ans; void cr(int x,int y) { tt++; b[tt]=y; next[tt]=first[x]; first[x]=tt; } bool cmp(int a,int b) { return d[a]>d[b]; } int main() { freopen("palingenesis.in","r",stdin); freopen("palingenesis.out","w",stdout); scanf("%d %d",&n,&m); fo(i,1,m) { scanf("%d %d",&x,&y); cr(x,y); cr(y,x); d[x]++; d[y]++; } fo(i,1,n) c[i]=i; sort(c+1,c+1+n,cmp); fo(i,1,n) ref[c[i]]=i; fo(i,1,n) for(p=first[i];p;p=next[p]) if (ref[b[p]]<ref[i]) tow[i][++tow[i][0]]=b[p]; fo(i,1,n) { for(p=first[i];p;p=next[p]) { fo(j,1,tow[b[p]][0]) { x=tow[b[p]][j]; if (ref[x]>ref[i]||x==i) continue; if (pd[x]!=i) { pd[x]=i; f[x]=1; }else { ans+=f[x]; f[x]++; } } } } printf("%lld",ans); }
相关文章推荐
- 【JZOJ5037】【NOI2017模拟3.30】轮回
- 【JZOJ5037】【NOI2017模拟3.30】轮回
- JZOI【NOI2017模拟3.30】轮回
- 【JZOJ5036】【NOI2017模拟3.30】原谅
- [JZOJ5036]【NOI2017模拟3.30】原谅
- 【NOI2017模拟3.30】轮回(根号算法,暴力)
- JZOJ【NOI2017模拟3.30】原谅
- 【JZOJ5046】【NOI2017模拟4.5】机器人游戏
- 【JZOJ 100019】【NOI2017模拟6.26】A
- 【NOI2017模拟3.30】原谅(计算几何,期望)
- [JZOJ5027]【NOI2017模拟3.25】历史行程
- JZOJ 100019【NOI2017模拟6.26】A
- [JZOJ5029]. 【NOI2017模拟3.25】围墙
- [JZOJ100003]【NOI2017模拟.4.1】 Tree
- [JZOJ5044]【NOI2017模拟4.4】Sone0
- 【JZOJ5180】【NOI2017模拟6.29】呵呵
- jzoj5043 【NOI2017模拟4.4】保持平衡 (可撤销贪心)
- [JZOJ100019] 【NOI2017模拟6.26】A
- [HackerRank Week of Code]Jogging Cats/[JZOJ5037]轮回
- 【NOI2017模拟3.30】原谅