Advertisement
Guest User

NAIPC18J_rpeng

a guest
Feb 16th, 2020
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.96 KB | None | 0 0
  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <cstring>
  5. using namespace std;
  6.  
  7. #define FR(i, a, b) for(int i=(a); i<(b); i++)
  8. #define FOR(i, n) FR(i, 0, n)
  9. #define PB push_back
  10.  
  11.  
  12. template <typename T> inline void SetMin(T &a, T b) {if(b < a) a = b;}
  13. template <typename T> inline void SetMax(T &a, T b) {if(b > a) a = b;}
  14.  
  15.  
  16. const int MAXN = 2000000;
  17.  
  18. vector<int> e[MAXN];
  19.  
  20. int parent[MAXN];
  21. vector<int> child[MAXN];
  22.  
  23. int cross_edge[MAXN];
  24. int cross_n;
  25. int e_low[MAXN];
  26. int e_high[MAXN];
  27.  
  28. int is_intermediate[MAXN];
  29.  
  30. int DP[MAXN][3][3][2];
  31.  
  32. int n, m;
  33. int vis[MAXN];
  34.  
  35.  
  36. int ans;
  37. const int VERYBIG = 1<<25;
  38.  
  39. int dfs_t;
  40. int disc[MAXN];
  41.  
  42. void DFS(int u, int pa) {
  43. vis[u] = 1;
  44. parent[u] = pa;
  45. disc[u] = dfs_t++;
  46. for(auto v: e[u]) {
  47. if(v != pa) {
  48. if(!vis[v]) {
  49. child[u].PB(v);
  50. DFS(v, u);
  51. } else if(disc[v] < disc[u]) {
  52. e_low[cross_n] = u;
  53. e_high[cross_n] = v;
  54. //printf("cross edge: %d--%d\n", u, v);
  55. int temp = u;
  56. while(temp != v) {
  57. //printf("%d\n", temp);
  58. if(cross_edge[temp] != -1) {
  59. puts("-1");
  60. exit(0);
  61. }
  62. cross_edge[temp] = cross_n;
  63. if(temp != u) {
  64. //printf("intermediate vertex = %d\n", temp);
  65. is_intermediate[temp] = 1;
  66. }
  67. temp = parent[temp];
  68. }
  69. cross_n++;
  70. }
  71. }
  72. }
  73. }
  74.  
  75. int Incorporate(int &mask, int v) {
  76. int opp = (4 - v) % 3;
  77. if(((mask >> opp) % 2) == 1) return 0;
  78. mask |= (1<<v);
  79. return 1;
  80. }
  81.  
  82. int bes[8], temp[8];
  83.  
  84. void Moo(int p, int pa) {
  85. for(auto v: child[p]) {
  86. Moo(v, p);
  87. }
  88.  
  89. int i1 = 0;
  90. if(is_intermediate[p]) {
  91. FOR(i, child[p].size()) {
  92. if(cross_edge[p] == cross_edge[child[p][i]]) {
  93. swap(child[p][i], child[p][0]);
  94. }
  95. }
  96. i1 = 1;
  97. }
  98. FOR(i, 8) bes[i] = VERYBIG;
  99. bes[0] = 0;
  100.  
  101. FR(i, i1, child[p].size()) {
  102. FOR(i, 8) temp[i] = VERYBIG;
  103. int v = child[p][i];
  104. if(cross_edge[v] == -1) {
  105. FOR(j1, 3) {
  106. FOR(mask, 8) {
  107. int mask1 = mask;
  108. if(Incorporate(mask1, j1)) {
  109. SetMin<int>(temp[mask1], bes[mask] + DP[v][j1][0][0]);
  110. }
  111. }
  112. }
  113. } else {
  114. FOR(j1, 3) FOR(j2, 3) {
  115. FOR(mask, 8) {
  116. int mask1 = mask;
  117. if(Incorporate(mask1, j1)) {
  118. if(Incorporate(mask1, j2)) {
  119. SetMin<int>(temp[mask1], bes[mask] + DP[v][j1][j2][1]);
  120. }
  121. }
  122. }
  123. }
  124. }
  125. FOR(i, 8) bes[i] = temp[i];
  126. }
  127. if(pa == -1) { //already at root, stop
  128. int blah = VERYBIG;
  129. FOR(mask, 8) {
  130. SetMin<int>(blah, bes[mask]);
  131. }
  132. if(blah > n * 3) {
  133. //printf("%d\n", DP[5][1][2][1]); fflush(stdout);
  134. //printf("%d\n", DP[2][2][2][1]); fflush(stdout);
  135. //printf("UHOH @ %d\n", p);
  136. puts("-1");
  137. exit(0);
  138. }
  139. ans += blah;
  140. } else if(is_intermediate[p]) { //intermediate vertex
  141. //printf("====intermediate====%d\n", p); fflush(stdout);
  142. int v = child[p][0];
  143. //printf("to...%d\n", v);
  144. FOR(j, 3) FOR(j1, 3) {
  145. FOR(mask, 8) {
  146. int mask1 = mask;
  147. //if(mask == 0 && j == 2 && j1 == 1) puts("HI");
  148. if(Incorporate(mask1, j)) {
  149. if(Incorporate(mask1, j1)) {
  150. FOR(j2, 3) FOR(j3, 2) {
  151. /*
  152. * if(mask == 0 && j == 2 && j1 == 1) {
  153. printf("%d, %d: %d\n", j2, j3, DP[v][j1][j2][j3]);
  154. }
  155. */
  156. SetMin<int>(DP[p][j][j2][(j3 + j) % 2],
  157. DP[v][j1][j2][j3] + j + bes[mask]);
  158. }
  159. }
  160. }
  161. }
  162. }
  163. } else if(cross_edge[p] == -1) { //only one parent, no cycle
  164. FOR(j, 3) {
  165. FOR(mask, 8) {
  166. int mask1 = mask;
  167. if(Incorporate(mask1, j)) {
  168. SetMin<int>(DP[p][j][0][0], bes[mask] + j);
  169. }
  170. }
  171. }
  172. } else { // parent + cross edge
  173. //printf("====bottom====%d\n", p); fflush(stdout);
  174. FOR(j, 3) FOR(k, 3) {
  175. FOR(mask, 8) {
  176. int mask1 = mask;
  177. if(Incorporate(mask1, j)) {
  178. if(Incorporate(mask1, k)) {
  179. //printf("%d %d\n", j, k);
  180. SetMin<int>(DP[p][j][k][(j + k) % 2], bes[mask] + j + k);
  181. }
  182. }
  183. }
  184. }
  185. }
  186. }
  187.  
  188. void ShowDFSStates() {
  189. FOR(i, n) printf("node %d: parent = %d cross = %d intermeidate = %d\n", i, parent[i], cross_edge[i], is_intermediate[i]);
  190. puts("cross edges");
  191. FOR(i, cross_n) printf("%d %d\n", e_low[i], e_high[i]);
  192. }
  193.  
  194. int main() {
  195. scanf("%d%d", &n, &m);
  196. FOR(i, m) {
  197. int a, b;
  198. scanf("%d%d", &a, &b);
  199. --a; --b;
  200. e[a].PB(b);
  201. e[b].PB(a);
  202. }
  203. ans = 0;
  204. memset(vis, 0, sizeof(vis));
  205. FOR(i, n) {
  206. is_intermediate[i] = 0;
  207. cross_edge[i] = -1;
  208. FOR(j1, 3) FOR(j2, 3) FOR(j3, 2) {
  209. DP[i][j1][j2][j3] = VERYBIG;
  210. }
  211. }
  212. cross_n = 0;
  213.  
  214. dfs_t = 0;
  215. ans = 0;
  216. FOR(i, n) {
  217. if(!vis[i]) {
  218. DFS(i, -1);
  219. //ShowDFSStates();
  220. Moo(i, -1);
  221. }
  222. }
  223. printf("%d\n", ans);
  224. return 0;
  225. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement