Advertisement
Guest User

Cycling City

a guest
Jun 25th, 2015
440
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.98 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define PII pair <int, int>
  4. const int MAXN = 200013;
  5. int N, M;
  6. vector <int> edges [MAXN];
  7. vector <int> spanning [MAXN];
  8. int vis [MAXN];
  9. int artic [MAXN];
  10. void mem ()
  11. {
  12.     memset(vis,0,sizeof(vis));
  13. }
  14. void create (int node) // create the spanning tree
  15. {
  16.     vis[node]=1;
  17.     for (int g=0; g<edges[node].size(); g++)
  18.     {
  19.         if (vis[edges[node][g]]) continue;
  20.         spanning[node].push_back(edges[node][g]);
  21.         spanning[edges[node][g]].push_back(node);
  22.         create(edges[node][g]);        
  23.     }  
  24. }
  25. int timer=1;
  26. int finishing [MAXN];
  27. int find (int node, int prev=0) // find articulation points
  28. {
  29.     vis[node]=1;
  30.     finishing[node]=timer++;
  31.     int mini=finishing[node];
  32.     for (int g=0; g<spanning[node].size(); g++)
  33.     {
  34.         if (vis[spanning[node][g]]) continue;
  35.         int k=find(spanning[node][g], node);
  36.         if (k>=finishing[node]) artic[node]=1;
  37.         if(k<mini)mini=k;
  38.     }
  39.     for (int g=0; g<edges[node].size(); g++)
  40.     {if(edges[node][g]==prev) continue;
  41.         if (finishing[edges[node][g]]<mini) mini=finishing[edges[node][g]];
  42.     }
  43.     return mini;
  44. }
  45. vector <int> artclear, path;
  46. int counter=0;
  47. vector <int> nodes;
  48. int iter [MAXN];
  49. int fromsame [MAXN];
  50. void determinesz (int node) // determine size of biconnected component & search it
  51. {
  52.     nodes.push_back(node); // add node to vector, so we know what nodes are part of biconnected component
  53.     vis[node]=1;
  54.     counter++;
  55.     if (artic[node]) { // if it is a articulation vertex, don't dfs further
  56.         artclear.push_back(node); return; // push it to a special vector
  57.     }
  58.     for (int g=0; g<edges[node].size(); g++)
  59.     {
  60.         if (vis[edges[node][g]]) continue;
  61.         determinesz (edges[node][g]); // dfs if it is not a articulation vertex
  62.     }
  63. }
  64. PII cyc (int node, int iteration, int prev=0) // cycle detection
  65. // note that the iteration counter here is useless; I thought the graph was directed at first :P
  66. {
  67.     iter[node]=iteration; // no use
  68.     vis[node]=1; // just visit the node
  69.     for (int g=0; g<edges[node].size(); g++)
  70.     {if(edges[node][g]==prev || fromsame[node]!=fromsame[edges[node][g]]) continue;
  71.     // if the node is the previous, or they don't belong to the same component, continue
  72.         if (vis[edges[node][g]])
  73.         {
  74.                 return PII(edges[node][g], node);  // cycle has been detected!
  75.             continue;
  76.         }
  77.         PII x = cyc (edges[node][g], iteration, node);
  78.         if (x.first!=-1) return x;
  79.     }
  80.     return PII(-1, -1);
  81. }
  82. int d=1;
  83. int findpath (int node1, int node2, int type=1)
  84. {
  85.     vis[node1]=1;
  86.     path.push_back(node1);if(node1==node2)return 1;
  87.     for (int g=0; g<edges[node1].size(); g++)
  88.     {
  89.         if (type && edges[node1][g]==node2) continue;
  90.         if (vis[edges[node1][g]] || fromsame[edges[node1][g]]!=fromsame[node1]) continue;
  91.         int x = findpath(edges[node1][g], node2, 0);
  92.         if (x==1) return 1;
  93.     }
  94.     path.pop_back();
  95.     return 0;
  96. }
  97. int oncyc [MAXN];
  98. vector <int> answer1, answer2, answer3;
  99. int doit (int node, int notequal)
  100. {
  101.     vis[node]=1;
  102.     if (oncyc[node])
  103.     {
  104.         answer1.push_back(node);
  105.         return 1;
  106.     }
  107.     answer1.push_back(node);
  108.     for (int g=0; g<edges[node].size(); g++)
  109.     {
  110.         if (fromsame[edges[node][g]]!=fromsame[node] || vis[edges[node][g]] || edges[node][g]==notequal) continue;
  111.         int t=doit(edges[node][g], notequal);
  112.         if (t) return 1;
  113.     }
  114.     answer1.pop_back(); return 0;
  115. }
  116. void solve (int node)
  117. {
  118.     counter=0;
  119.     determinesz (node);
  120.     if (counter<=2) return;
  121.     for (int t=0; t<nodes.size(); t++) vis[nodes[t]]=0, fromsame[nodes[t]]=d;
  122.     d++;  
  123.     int z=1;
  124.     PII r=cyc(nodes[0], 1); // this is for detecting a cycle in the graph; and finding the edge where the problem occurred
  125.         // through some debugging, I've found that somehow no cycle is found in the biconnected component
  126.         // leading me to believe that either the cycle detection is wrong or articulation point detection is wrong
  127.         // or I'm somehow finding biconnected components in a wrong way.
  128.         // However, I haven't been able to find problems with any
  129.     for (int t=0; t<nodes.size(); t++) vis[nodes[t]]=0, iter[nodes[t]]=0;
  130.     findpath(r.first, r.second); // just finds a path between two nodes given edge; but this is not the problem I think
  131.     for (int t=0; t<nodes.size(); t++) vis[nodes[t]]=0;
  132.     if (counter==path.size())
  133.     {
  134.         for (int g=0; g<nodes.size(); g++)
  135.         {
  136.             if (artic[nodes[g]]) continue;
  137.             vis[nodes[g]]=1;
  138.         }
  139.         return;  
  140.     }
  141.     for (int t=0; t<path.size(); t++) oncyc[path[t]]=1;
  142.     cout << "YES" << '\n';
  143.     int start=-1, other=-1, end=-1;
  144.     for (int t=0; t<path.size(); t++)
  145.     {
  146.         int nodcyc=path[t];
  147.         for (int y=0; y<edges[nodcyc].size(); y++)
  148.         {
  149.             if (fromsame[edges[nodcyc][y]]!=fromsame[path[t]]) continue;
  150.             if (oncyc[edges[nodcyc][y]]) continue;
  151.             start=path[t], other=edges[nodcyc][y];
  152.         }
  153.         if (start!=-1) break;
  154.     }
  155.     doit(other, start);
  156.     for (int t=0; t<nodes.size(); t++) vis[nodes[t]]=0;
  157.     cout << answer1.size()+1 << ' ' << start << ' ';
  158.     for (int g=0; g<answer1.size(); g++) cout << answer1[g] << ' ';
  159.     cout << '\n';
  160.     end=answer1.back();
  161.     int pos1=-1, pos2=-1;
  162.     for (int t=0; t<path.size(); t++)
  163.     {
  164.         if (path[t]==start) pos1=t;
  165.         if (path[t]==end) pos2=t;
  166.     }
  167.     if (pos2>pos1)
  168.     {
  169.         cout << pos2-pos1+1 << ' ';
  170.         for (int g=pos1; g<=pos2; g++) cout << path[g] << ' '; cout << '\n';
  171.         cout << (pos1+1+(path.size()-pos2)) << ' ';
  172.         for (int g=pos1; g>=0; g--) cout << path[g] << ' ';
  173.         for (int g=path.size()-1; g>=pos2; g--) cout << path[g] << ' '; cout << '\n';
  174.     }
  175.     else
  176.     {
  177.         cout << (path.size()-pos1)+(pos2+1) << ' ';
  178.         for (int g=pos1; g<path.size(); g++) cout << path[g] << ' ';
  179.         for (int g=0; g<=pos2; g++) cout << path[g] << ' '; cout << '\n';
  180.         cout << pos1-pos2+1 << ' ';
  181.         for (int g=pos1; g>=pos2; g--) cout << path[g] << ' ';
  182.         cout << '\n';
  183.     }
  184.     exit(0);
  185. }
  186. int main()
  187. {
  188.     ios_base::sync_with_stdio(0);
  189.     cin >> N >> M;
  190.     for (int g=0; g<M; g++)
  191.     {
  192.         int a, b; cin >> a >> b;
  193.         edges[a].push_back(b);
  194.         edges[b].push_back(a);  
  195.     }  
  196.     for (int g=1; g<=N; g++)
  197.     {
  198.         if (vis[g]) continue;
  199.         create (g);
  200.     }
  201.     mem();
  202.     for (int g=1; g<=N; g++)
  203.     {
  204.         if (vis[g]) continue;
  205.         find(g);
  206.         if (spanning[g].size()>1) artic[g]=1;
  207.         else artic[g]=0;
  208.     }
  209.     mem();
  210.     for (int g=1; g<=N; g++)
  211.     {
  212.         if (vis[g] || artic[g]) continue;
  213.         solve (g);  
  214.         for (int t=0; t<artclear.size(); t++) vis[artclear[t]]=0;
  215.         artclear.clear();
  216.         path.clear();
  217.         nodes.clear();
  218.     }
  219.     cout << "NO" << '\n';
  220.     return 0;
  221. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement