ariacas

Untitled

May 13th, 2018
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.98 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long double ld;
  4. typedef long long ll;
  5. typedef pair<double, double> pdd;
  6. typedef vector<double> vd;
  7. typedef vector<vd> vvd;
  8. typedef vector<ll> vl;
  9. typedef vector<vl> vvl;
  10. typedef pair<int, int> pii;
  11. typedef vector<pii> vii;
  12. typedef vector<int> vi;
  13. typedef vector<vi> vvi;
  14. typedef vector<string> vs;
  15.  
  16. struct TEdge {
  17. int from, to;
  18. ll capacity, flow;
  19. TEdge* reverse;
  20. };
  21.  
  22. TEdge edgePool[1000000];
  23. int edgePoolPtr = 0;
  24.  
  25. typedef vector<TEdge*> ve;
  26. vector< ve > edges; //resize
  27. int col[1000000];
  28.  
  29. int SOURCE, TARGET; //assign
  30.  
  31. TEdge* AddEdge(int from, int to, ll capacity) {
  32. TEdge* e1 = &edgePool[edgePoolPtr++];
  33. TEdge* e2 = &edgePool[edgePoolPtr++];
  34. TEdge fw = {from, to, capacity, 0, e2};
  35. TEdge bw = {to, from, 0, 0, e1};
  36. *e1 = fw;
  37. *e2 = bw;
  38. edges[from].push_back(e1);
  39. edges[to].push_back(e2);
  40. return e1;
  41. }
  42.  
  43. inline ll AvailableCapacity(const TEdge* p) {
  44. return (p->capacity - p->flow);
  45. }
  46.  
  47. class TDinic {
  48. public:
  49. vector<int> Distances;
  50. vector<size_t> Ptr;
  51. int N;
  52. void BFS() {
  53. deque<int> q;
  54. Distances.assign(N, -1);
  55. Distances[SOURCE] = 0;
  56. q.push_back(SOURCE);
  57. while (!q.empty()) {
  58. int p = q.front();
  59. q.pop_front();
  60. for (size_t i = 0; i < edges[p].size(); i++) {
  61. if (!AvailableCapacity(edges[p][i]))
  62. continue;
  63. int c = edges[p][i]->to;
  64. if (Distances[c] == -1) {
  65. Distances[c] = Distances[p] + 1;
  66. q.push_back(c);
  67. }
  68. }
  69. }
  70. }
  71. ll DFS(int p, ll fl) {
  72. if (fl == 0)
  73. return 0;
  74. if (p == TARGET)
  75. return fl;
  76. ll res = 0;
  77.  
  78. for (size_t &i = Ptr[p]; Ptr[p] < edges[p].size() && fl != 0; ++i) {
  79. if (!AvailableCapacity(edges[p][i])) {
  80. continue;
  81. }
  82. if (Distances[edges[p][i]->from] + 1 != Distances[edges[p][i]->to])
  83. continue;
  84. ll pushed = DFS(edges[p][i]->to, min(fl, AvailableCapacity(edges[p][i])));
  85. fl -= pushed;
  86. res += pushed;
  87. edges[p][i]->flow += pushed;
  88. edges[p][i]->reverse->flow -= pushed;
  89. if (fl == 0)
  90. break;
  91. }
  92. return res;
  93. }
  94. /*void init() {
  95. SOURCE,TARGET
  96. edges.clear();
  97. edgePoolPtr = 0;
  98. edges.resize();
  99. }*/
  100. ll calc_max_flow() {
  101. N = (int)edges.size();
  102. ll res = 0;
  103. while (true) {
  104. BFS();
  105. Ptr.assign(N, 0);
  106. ll p = DFS(SOURCE, LLONG_MAX / 2);
  107. if (!p)
  108. break;
  109. res += p;
  110. }
  111. return res;
  112. }
  113. };
  114.  
  115. struct Graph {
  116. void read() {
  117. int m;
  118. cin >> n >> m;
  119.  
  120. e.resize(n);
  121.  
  122. for (int i = 0; i < m; ++i) {
  123. int u, v;
  124. cin >> u >> v;
  125. --u; --v;
  126. e[u].push_back(v);
  127. e[v].push_back(u);
  128. }
  129. }
  130.  
  131. /* COMMON PART */
  132.  
  133. int n;
  134. vector<vector<int>> e;
  135.  
  136. int counter = 1;
  137. vector<int> inTime, minInTime;
  138.  
  139. void dfs(int v, int p = -1) {
  140. minInTime[v] = inTime[v] = counter++;
  141.  
  142. for (int u: e[v]) {
  143. if (u == p) continue;
  144.  
  145. if (!inTime[u]) {
  146. dfs(u, v);
  147. minInTime[v] = min(minInTime[v], minInTime[u]);
  148. }
  149. else {
  150. minInTime[v] = min(minInTime[v], inTime[u]);
  151. }
  152. }
  153. }
  154.  
  155. vector<char> used;
  156.  
  157. /* COMPONENTS SEPARATED BY BRIDGES (COLORING) */
  158.  
  159. int nColors;
  160. vector<int> color;
  161.  
  162. void colorDfs(int v, int curColor) {
  163. color[v] = curColor;
  164.  
  165. for (int u: e[v]) {
  166. if (color[u] != -1) continue;
  167.  
  168. colorDfs(u, minInTime[u] > inTime[v] ? nColors++ : curColor);
  169. }
  170. }
  171.  
  172. void findVertexComponents() {
  173. inTime.assign(n, 0);
  174. minInTime.assign(n, 0);
  175. counter = 1;
  176.  
  177. for (int i = 0; i < n; ++i)
  178. if (!inTime[i])
  179. dfs(i);
  180.  
  181. nColors = 0;
  182. color.assign(n, -1);
  183. for (int i = 0; i < n; ++i)
  184. if (color[i] == -1) {
  185. colorDfs(i, nColors++);
  186. }
  187. }
  188.  
  189. /* COMPONENTS SEPARATED BY JOINTS (EDGE COMPONENTS) */
  190.  
  191. struct Edge {
  192. int u, v;
  193. };
  194.  
  195. // Cactus loops can be parsed as .u of every edge
  196. vector<vector<Edge>> edgeComps;
  197.  
  198. vector<int> colorStack;
  199.  
  200. void edgeCompDfs(int v, int p = -1) {
  201. used[v] = true;
  202.  
  203. for (int u: e[v]) {
  204. if (used[u]) {
  205. if (inTime[u] < inTime[v] && u != p) {
  206. // NOTE: && u != p makes one-edge components contain exactly one edge;
  207. // if you need them as two-edge loops, remove this part of if condition
  208. edgeComps[colorStack.back()].push_back({v, u});
  209. }
  210.  
  211. continue;
  212. }
  213.  
  214. bool newComp = minInTime[u] >= inTime[v];
  215.  
  216. if (newComp) {
  217. colorStack.push_back(edgeComps.size());
  218. edgeComps.emplace_back();
  219. }
  220.  
  221. edgeComps[colorStack.back()].push_back({v, u});
  222. edgeCompDfs(u, v);
  223.  
  224. if (newComp) {
  225. colorStack.pop_back();
  226. }
  227. }
  228. }
  229.  
  230. void findEdgeComponents() {
  231. inTime.assign(n, 0);
  232. minInTime.assign(n, 0);
  233. counter = 1;
  234.  
  235. for (int i = 0; i < n; ++i)
  236. if (!inTime[i])
  237. dfs(i);
  238.  
  239. used.assign(n, false);
  240. colorStack.clear();
  241. edgeComps.clear();
  242. for (int i = 0; i < n; ++i)
  243. if (!used[i]) {
  244. assert(colorStack.empty());
  245. edgeCompDfs(i);
  246. }
  247. }
  248. };
  249.  
  250.  
  251. int main() {
  252. std::ios::sync_with_stdio(false); std::cin.tie(0);
  253. Graph g;
  254. g.read();
  255. for (int i = 0; i < g.n; ++i) {
  256. cin >> col[i];
  257. --col[i];
  258. }
  259. g.findEdgeComponents();
  260. for (auto v : g.edgeComps) if (v.size() > 1) {
  261. vi was(3, -1);
  262. for (auto e : v) {
  263. was[col[e.u]] = e.u;
  264. was[col[e.v]] = e.v;
  265. cerr << e.u+1 << ' ' << e.v+1 << '|';
  266. }
  267. cerr << endl;
  268. for (auto e : v) {
  269. if (col[e.u] != col[e.v]) {
  270. int remcol = 3 - col[e.u] - col[e.v];
  271. int root = was[remcol];
  272. if (root < 0) break;
  273. map<int, int> ind;
  274. vi invind;
  275. for (auto e1 : v) {
  276. for (int x : {e1.v, e1.u}) if (!ind.count(x)) {
  277. ind[x] = invind.size();
  278. invind.push_back(x);
  279. }
  280. }
  281. cerr << ind.size() << ' ' << invind.size() << ' ' << root + 1 << endl;
  282. TDinic flow;
  283. edges.clear();
  284. edgePoolPtr = 0;
  285. SOURCE = 2 * ind[root] + 1, TARGET = 2 * ind[e.u] + 1;
  286. edges.resize(invind.size() * 2);
  287. assert(TARGET < edges.size());
  288. for (auto e1 : v) {
  289. if (pii(e1.u, e1.v) != pii(e.u, e.v)) {
  290. if (e1.v != root) AddEdge(2 * ind[e1.u] + 1, 2 * ind[e1.v], 1);
  291. if (e1.u != root) AddEdge(2 * ind[e1.v] + 1, 2 * ind[e1.u], 1);
  292. }
  293. }
  294. for (int i = 0; i < invind.size(); ++i) {
  295. if (invind[i] != e.v) {
  296. AddEdge(2 * i, 2 * i + 1, 1);
  297. } else {
  298. AddEdge(2 * i, TARGET, 1);
  299. }
  300. }
  301. assert(flow.calc_max_flow() == 2);
  302. cout << "YES\n";
  303. vi res(1, root);
  304. for (auto ef : edges[SOURCE]) {
  305. if (ef->from == SOURCE && ef->flow) {
  306. vi path;
  307. int cur = ef->to;
  308. cerr << invind[SOURCE / 2] + 1 << ' ' << 1 + invind[TARGET / 2] << " HUI\n";
  309. while (cur != TARGET) {
  310. cerr << cur << ' ' << 1 + invind[cur / 2] << endl;
  311. bool fail = 1;
  312. if (cur % 2 == 0) path.push_back(cur);
  313. for (auto ef1 : edges[cur]) {
  314. if (ef1->from == cur && ef1->flow) {
  315. ef1->flow = 0;
  316. cur = ef1->to;
  317. fail = 0;
  318. break;
  319. }
  320. }
  321. assert(!fail);
  322. }
  323. if (res.size() > 1) reverse(path.begin(), path.end());
  324. for (int x : path) res.push_back(invind[x]);
  325. }
  326. }
  327. cout << res.size() << endl;
  328. for (int x : res) cout << x + 1 << ' '; cout << endl;
  329. break;
  330. }
  331. }
  332. }
  333. cout << "NO\n";
  334. return 0;
  335. }
Advertisement
Add Comment
Please, Sign In to add comment