description:
A tournament is a directed graph without self-loops in which every pair of vertexes is connected by exactly one directed edge. That is, for any two vertexes u and v (u ≠ v) exists either an edge going from u to v, or an edge from v to u.
You are given a tournament consisting of n vertexes. Your task is to find there a cycle of length three.
输入的图以邻接矩阵的形式给出,A->B有边则map[A][B]=1,顶点数量上限是5000,若存在3元环,则输出任意一组即可,否则输出-1。
这是codeforces beta round# 88的C题,当时做的时候因为状态不佳,A题花了太多时间,导致没来的及做,事后做了做这题,发现还是很有意思的。
我一开始的思路是将矩阵平方,这样可以得到顶点之间路径长度为2的可达矩阵,然后再和原矩阵进行比较,若A到B存在长度为2的路径,并且B到A有边,那么这就形成了一个三元环。可惜,矩阵平方的复杂度是3次方的,此题顶点的个数为10^3数量级,实践证明超时。
后来看版的时候看到了edward_mj大牛,看了他的代码没看懂,发了talk问他。edward_mj的做法是:一个一个点加进去,每次Judge是否生成了3元环.是的话.暴力找出另外两个点。
现在问题是每次加一个点后如何快速判断是否生成了3元环,后来经过指点终于明白,比如已经加入了N个点,这N个点之间没有形成3元环,此时加入第N+1个点,那么如果存在3元环,肯定是这个新加入的点与之前集合中的N个点之间的两个形成了3元环。根据新加入的点可以将原来的N点集合分成两部分P1和P2,P1是新加入点到其中每个点有边,P2是其中每个点到新加入点有边,这点非常重要,因为根据题目,every pair of vertexes is connected by exactly one directed edge,不存在两个顶点之间没有边的情况。那么现在就只要P1到P2可达就可以了,也就是说至少P1中要存在一个点有一条有向边指向P2中的一个点,如何判断呢?还是注意到题中的那个条件,如果P2中的每个点都指向P1中的所有点,那么就无3元环,否则,必有P1中一点指向P2中一点,那么就存在三元环。这个判断可以通过顶点的度数进行。
在每次新加入顶点之后,更新集合中顶点的入度和出度,那么在新加入第N+1点时,前N个顶点组成的子图中每个顶点的入度和出度都已经获得,统计下P1中所有顶点的入度和Sin、出度和Sout,P1中点的个数x,P2中点的个数y,如果Sin==Sout+x*y,那么就说明P2中的每个点都指向P1中的所有点,P1到P2不可达。这是因为子图中顶点的入度和应等于出度和,如果满足上式,就说明P1中的点已经用完了所有入度,P2中的点只贡献出度。
显然,若Sin!=Sout+x*y时,存在3元环。此时只需找出即可。整体为平方复杂度。