@@ -26,13 +26,21 @@ public class Code04_TeamBuilding1 {
2626 public static int MAXN = 500001 ;
2727 public static int n , m , k ;
2828
29+ // 每个节点的颜色
2930 public static int [] color = new int [MAXN ];
31+ // 每条边有两个端点
3032 public static int [][] edge = new int [MAXN ][2 ];
33+
34+ // 两个端点为不同颜色的边,u、ucolor、v、vcolor
3135 public static int [][] crossEdge = new int [MAXN ][4 ];
36+ // 两个端点为不同颜色的边的数量
3237 public static int cnt = 0 ;
3338
39+ // conflict[i] = true,表示颜色为i的组,组内即便是二分图,也无法调和矛盾
40+ // conflict[i] = false,表示颜色为i的组,组内构成二分图,可以调和矛盾
3441 public static boolean [] conflict = new boolean [MAXN ];
3542
43+ // 可撤销并查集
3644 public static int [] father = new int [MAXN << 1 ];
3745 public static int [] siz = new int [MAXN << 1 ];
3846 public static int [][] rollback = new int [MAXN << 1 ][2 ];
@@ -102,19 +110,20 @@ public static void filter() {
102110 public static long compute () {
103111 Arrays .sort (crossEdge , 1 , cnt + 1 , (a , b ) -> a [1 ] != b [1 ] ? (a [1 ] - b [1 ]) : (a [3 ] - b [3 ]));
104112 long ans = (long ) k * (k - 1 ) / 2 ;
113+ int u , ucolor , v , vcolor , unionCnt ;
105114 for (int l = 1 , r = 1 ; l <= cnt ; l = ++r ) {
106- while (r + 1 <= cnt && crossEdge [r + 1 ][1 ] == crossEdge [l ][1 ] && crossEdge [r + 1 ][3 ] == crossEdge [l ][3 ]) {
115+ ucolor = crossEdge [l ][1 ];
116+ vcolor = crossEdge [l ][3 ];
117+ while (r + 1 <= cnt && crossEdge [r + 1 ][1 ] == ucolor && crossEdge [r + 1 ][3 ] == vcolor ) {
107118 r ++;
108119 }
109- int u , ucolor , v , vcolor , unionCnt = 0 ;
120+ if (conflict [ucolor ] || conflict [vcolor ]) {
121+ continue ;
122+ }
123+ unionCnt = 0 ;
110124 for (int i = l ; i <= r ; i ++) {
111125 u = crossEdge [i ][0 ];
112- ucolor = crossEdge [i ][1 ];
113126 v = crossEdge [i ][2 ];
114- vcolor = crossEdge [i ][3 ];
115- if (conflict [ucolor ] || conflict [vcolor ]) {
116- break ;
117- }
118127 if (find (u ) == find (v )) {
119128 ans --;
120129 break ;
0 commit comments