Counting Stars
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1146 Accepted Submission(s): 315
Problem Description
Little A is an astronomy lover, and he has found that the sky was so beautiful!
So he is counting stars now!
There are n stars in the sky, and little A has connected them by m non-directional edges.
It is guranteed that no edges connect one star with itself, and every two edges connect different pairs of stars.
Now little A wants to know that how many different "A-Structure"s are there in the sky, can you help him?
An "A-structure" can be seen as a non-directional subgraph G, with a set of four nodes V and a set of five edges E.
If V=(A,B,C,D) and E=(AB,BC,CD,DA,AC), we call G as an "A-structure".
It is defined that "A-structure" G1=V1+E1 and G2=V2+E2 are same only in the condition that V1=V2 and E1=E2.
Input
There are no more than 300 test cases.
For each test case, there are 2 positive integers n and m in the first line.
2≤n≤105, 1≤m≤min(2×105,n(n−1)2)
And then m lines follow, in each line there are two positive integers u and v, describing that this edge connects node u and node v.
1≤u,v≤n
∑n≤3×105,∑m≤6×105
Output
For each test case, just output one integer--the number of different "A-structure"s in one line.
Sample Input
4 5 1 2 2 3 3 4 4 1 1 3 4 6 1 2 2 3 3 4 4 1 1 3 2 4
Sample Output
1 6
Source
2017ACM/ICPC广西邀请赛-重现赛(感谢广西大学)
大致题意:给你一个图,然后找所有满足含有4个点5条边的子图有多少种。这里不同的点的定义是,只要有一条边不同,那么就是不同的子图。
可以发现,满足这样的条件的子图,最后一定能够画成两个有公共边的三元环。那么我们的任务就是找这样的三元环。做法的话很容易知道是暴力,但是这个暴力并不是简单的暴力。我的想法是,枚举每一条边,然后对于这条边的两个端点,我分别拓展它们能够到达的点,求出公共点的数量t,这样能够组成的满足条件的三元环个数就是t*(t-1)/2.虽然理论的时间不复杂度不好计算,但是应该是可以的。但是结果确实TLE……
然后至于正解还是不得不服暴力方法的巧妙。首先,我们考虑另外一个问题:如何求一个图的三元环。对于这个问题,我们肯定还是枚举每一条边,边然后找边上两端点能够到达的公共点。但是这里找公共点不是简单的枚举,而是要分类讨论。对于每一个点,我首先求一下度,然后根据这个度来分类讨论。
①统计每个点的度数
②入度<=sqrt(m)的分为第一类,入度>sqrt(m)的分为第二类
③对于第一类,暴力每个点,然后暴力这个点的任意两条边,再判断这两条边的另一个端点是否连接
因为m条边最多每条边遍历一次,然后暴力的点的入度<=sqrt(m),所以复杂度约为O(msqrt(m))
④对于第二类,直接暴力任意三个点,判断这三个点是否构成环,因为这一类点的个数不会超过sqrt(m)个,
所以复杂度约为O(sqrt(m)^3)=O(msqrt(m))
⑤判断两个点是否连接可以用set,map和Hash都行
具体到这道题目,也是利用类似的方法。我们首先枚举边,其实相当于枚举点,枚举一个点x,然后选择与它相连的一条边,边的另一端作为第二个点y,与此同时保存下其他与点相连的边。然后我们判断y的度,如果y的度大于sqrt(m),那么相当于第二类点,于是我第三个点就在之前保存的与x相连的其他点中找公共点。这样就相当于找三元环的第二类对应的方法。如果y的度小于sqrt(m),那么相当于之前说的第一类,我们只需要再枚举y能到达的所有点即可。这样处理好公共点次数之后,最后贡献就是t*(t+1)/2。这样我们就可以计算出理论的时间复杂度O(N^1.5)。恰好可以通过这道题,具体见代码: