Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added implementation of Dinic's #82

Merged
merged 6 commits into from
Apr 27, 2019

Conversation

Chillee
Copy link
Collaborator

@Chillee Chillee commented Apr 26, 2019

Comes in at 42 lines and 800 non-whitespace characters, compared to 36 lines and 592 non-whitespace characters for Edmonds-Karp, and 46 lines and 761 non-whitespace characters for Hopcroft-Karp. Note that about 4 of these lines and 100 of the characters are due to addEdge (whereas you need to add edges yourself for Edmonds-Karp).

Unluckily, it seems to run at 0.45 seconds on SPOJ MATCHING compared to 0.15 from Hopcroft-Karp... In addition, it doesn't return the matches themselves like Hopcroft-Karp it does.

For now I haven't included it in the document - I think that's another discussion. See #75 .

@simonlindholm
Copy link
Member

Looks good. Golfed to 40 lines and 678 characters. (Counted by tr -d '[:space:]' | wc -c; Edmonds-Karp gets 556 by the same measure.) Then ungolfed to 42 lines and 704 chars because you need to do a full blocking flow to get the right time complexity. Double-check me and I'll merge.

@Chillee
Copy link
Collaborator Author

Chillee commented Apr 27, 2019

Looks good to me! I think the issue with the full blocking flow is actually important, nice catch. It seems to make a large difference on the LOJ flow problem. (whups, misremembered the previous results). BTW, it is possible to get substantially better worst case complexity (VE log U, where U is the maximum edge capacity) with the following alteration to calc.

        for (int lim = (1 << 30); lim > 0; lim >>= 1) {
            do {
                lvl = ptr = vi(sz(q));
                int qi = 0, qe = lvl[s] = 1;
                while (qi < qe && !lvl[t]) {
                    int v = q[qi++];
                    trav(e, adj[v]) 
                        if (!lvl[e.to] && e.f < e.c && e.c - e.f >= lim) 
                            q[qe++] = e.to, lvl[e.to] = lvl[v] + 1;
                }
                while (ll p = dfs(s, t, LLONG_MAX))
                    flow += p;
            } while (lvl[t]);
        }

We could just put this in by default and note that if lim=1 instead of 1<<30, it's the same as regular Dinic's.

@Chillee
Copy link
Collaborator Author

Chillee commented Apr 27, 2019

As with our discussion, the original version is already doing a full blocking flow.

@simonlindholm simonlindholm merged commit 84fca96 into kth-competitive-programming:master Apr 27, 2019
@simonlindholm
Copy link
Member

Right, I misparsed how the ptr stuff worked. ... also, right, perhaps merged too early, given the scaling thing. Let's do that in another PR if we decide to, I guess.

@simonlindholm
Copy link
Member

Added scaling in b552ece.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants