Hi;
can you help me with this problem?:
We have DAG with n vertices and m edges. We have q queries, each query has two integers v[i] and u[i], determine for each query that if there is a path starting at v[i] and finishing at u[i].
n, m, q <= 1e5
thanks, and sorry for my bad English. (:
[Deleted]
Pay attention to the constraints. You're not able to do dfs for each query.
Seems like top sort. You can use the half idea of SCC. Problem link please?
How?
This idea for the blog post's problem seems right to me. Help me if I'm wrong. I couldn't find any problem like that. Give me if you have any. The link you gave, have 2800 complexity. So, it's better for me now to stay away. Maybe later. Thank You.
I don't really understand your algorithm, but I think this can't possibly be correct. Look at this simple DAG:
If I understood correctly, then you claim there's a path from $$$u$$$ to $$$v$$$ if and only if $$$u$$$ and $$$v$$$ have the same visited marker. Because there is a path from 1 to 2 they must have the same marker. But then there must be a path from 2 to 1 because they have the same marker, which isn't true.
Sorry, my algorithm broke in the following graph. 1 -> 2 2 -> 3 2 -> 4 5 -> 4 It was a mistake.
So what to do after top sort?
There is no guarantee that if u is after v in a top sort, so there is a path from v to u.
It seems that 555E - Дело о компьютерной сети can be solved by a combination of SCC and this problem.
I think I'm an idiot today, I can't see the connection between 555E and your problem either.
If you're interested here's how I would do 555E:
Temporarily remove all bridges from the graph. In each connected component, it's possible to direct each edge such that the component is strongly connected. Squeeze each component down to a single vertex. Now you have to solve the same problem, except it's on a tree. You can easily tell whether a tree edge is supposed to go up or down, if there is a conflict then the answer is No.
If I correctly understood the problem statement my solution is this:
Let G be the main graph and H be the graph with each of q queries as edges. Use Tarjan's algorithm for SCC decomposition on H. You have to make an orientation on G so that for each two vertices in H that are in the same SCC(v, u), there is a path from v to u in G and also a path from u to v. It is equal to this: "Having set S of vertices (Where vertices in S are in the same SCC in H), check if the subgraph of G induced with S has a bridge or not." (We can prove it later).
So we oriented edges in G that two vertices of them are in same SCC in H. It remains to orient edges that are between two different SCCs in H. I considered this as the same problem as explained in the post.
Sorry for my bad English. If some sentences of my solution is not obvious for you, ask for proof.
There's a well-known approach for finding all such pairs using bitsets. Let's say that the vertices are numbered $$$0$$$ through $$$N-1$$$ in reverse topological order and for each vertex $$$v$$$, there's a bitset with $$$v$$$ bits where the $$$u$$$-th bit is 1 if there's a path from $$$v$$$ to $$$u$$$. For each edge $$$v \rightarrow u$$$, you just OR the bitset for $$$v$$$ with the bitset for $$$u$$$ and make sure the $$$u$$$-th bit is also $$$1$$$ (since that wasn't in the bitset).
This takes $$$N^2/2$$$ bits of memory, which is approx. 600 MB, and at most $$$NM/64$$$ bitwise operations (on a 64-bit machine), which is approx. 150 million, with no extra cache misses. Not that much.
consider that time limit is 64 MB.
So it's a problem from a specific OJ?
Heuristics.
No; But I'm using it to solve 555E - Дело о компьютерной сети; and the time limit is 256 MB; but the constraints is 2e5 not 1e5; so I devided the time limit by 4.
These aren't queries!
Look at this comment: https://codeforces.net/blog/entry/69481?#comment-539810
It's possible to transform a problem into a more general one that isn't solvable under the constraints of the original problem — it happened to me many times. Your solution to the original problem can be correct (or wrong) and it wouldn't affect the constraints you demand for this specific version.
In this case, riadwaw's suggestion below works, so even this version is solvable with low memory. I'd choose a higher block size than 64 though (as large as possible) to keep cache efficiency and possible compiler optimisations through loop unrolling and SIMD.
Is there a better solution than O(NM/64) time complexity within 1024MB of Memory
Heuristics.
Let's solve it for all destinations 0..63 in O(M) and O(n) memory, remember all results, then clear the memory and solve for all destinations 64..127 etc
I think it should be possible to process all queries offline using the smaller-to-larger optimization.
there is no possible way of managing that because its a dag and a node can have more than 1 parent
I got one idea, however I'm not sure if it will work, maybe some of the more experienced coders could check my work.
For simplicity, Let's assume that the there is just one vertex with no parents.
Let's start by picking one DFS tree of the given DAG (rooted at the node without parents). Now, we can notice that since the graph is DAG each edge in the graph will either be tree edge or edge that link current node to some other subtree. For each node we keep list of all the subtrees this node has links. It seems pretty clear that node $$$u$$$ is reachable from node $$$v$$$ if $$$u$$$ is in some subtree of $$$v$$$.
With clever implementation and using binary search we can store all the subtrees each node has links to and we can answer each query in $$$O(\log N)$$$.
Are you sure this is an innocent "without loss of generality..." assumption? Does your solution generalize?
Can you explain how you plan to do this? Right now you sound a bit like "and then we solve the problem by solving the problem".
It seems like the problem is when there are more roots.
Since in total there are M edges, for each tree we build we can use euler tour to be able to store the subtrees as consecutive intervals, then for each node we store all the subtrees this node can cover, as intervals, then the query is reduced to check if one number is present at one of the intervals, and this can be checked binary search.
When there are multiple vertices without parents, you can just add one dummy vertex that has edges to all of them. It doesn't affect reachability.
I didn't know about this trick of adding dummy vertex, are there more cases or problems when we can add dummy vertex to simplify things?
So what about memory?