@atcoder - AGC038F@ Two Permutations


@description@

Given two P replaced with N 0 ~ N-1 is, Q.
Now you need to find two permutations A and B, such that A [i] = P [i ] or i; B [i] = Q [i] or i.
I is the number of B [i] is maximized A [i] ≠. Maximum output.

The Constraints
. 1 ≤ N ≤ 100000..
It is arranged to ensure that P 0 ~ N-1 is.
Q is arranged to ensure that 0 ~ N-1 is.

Input
Input following form:
N
P0 Pl. 1 ⋯ the PN-
Q0-QN. 1 ⋯ Ql

Output
Output A [i] ≠ i of the maximum number of B [i] is.

Sample Input 1
4
2 1 3 0
0 2 3 1
Sample Output 1
3

One solution is A = (0,1,2,3), B = (0,2,3,1).

Sample Input 2
10
0 4 5 3 7 8 2 1 9 6
3 8 5 6 4 0 2 1 7 9
Sample Output 2
8

Sample Input 3
32
22 31 30 29 7 17 16 3 14 9 19 11 2 5 10 1 25 18 15 24 20 0 12 21 27 4 26 28 8 6 23 13
22 3 2 7 17 9 16 4 14 8 19 26 28 5 10 1 25 18 15 13 11 0 12 23 21 20 29 24 27 6 30 31
Sample Output 3
28

@solution@

For the replacement of P, we break it down into several cycles.
Then for each cycle, either simultaneously selected becomes i, while maintaining or P [i] unchanged.
Each element has two options, but will affect each other choice, people not think of 2-sat is the thought of minimal cut (which implies a minimum time limit further cut!).

Minimum cut transformation: We find the smallest A [i] = B [i ] number.
For each cycle, we build a virtual point to all points in the cycle even capacity of two-way side inf.
The rest is a classic binary relationships built map (ie: while the cost of the election will produce problems like).

For each Pi, which represents the source connected to the selected i, Pi is selected to connect it represents sink.
For each Qi, which represents the source connected to the selected Qi, i selected indicates that even the sink.
The edge is then classified built equal relationship between i, Pi, Qi. Specific can look at the code.
As for why the asymmetry built, because the symmetrical construction will produce a negative right side, is not good.

@accepted code@

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100000;
const int INF = (1<<30);
struct FlowGraph{
    struct edge{
        int to, cap, flow;
        edge *nxt, *rev;
    }edges[20*MAXN + 5], *adj[4*MAXN + 5], *cur[4*MAXN + 5], *ecnt;
    FlowGraph() {ecnt = &edges[0];}
    void addedge(int u, int v, int c1, int c2) {
        edge *p = (++ecnt), *q = (++ecnt);
        p->to = v, p->cap = c1, p->flow = 0;
        p->nxt = adj[u], adj[u] = p;
        q->to = u, q->cap = c2, q->flow = 0;
        q->nxt = adj[v], adj[v] = q;
        p->rev = q, q->rev = p;
//      printf("! %d %d %d %d\n", u, v, c1, c2);
    }
    int dis[4*MAXN + 5];
    int s, t;
    bool relabel() {
        for(int i=0;i<=t;i++)
            dis[i] = INF, cur[i] = adj[i];
        queue<int>que; que.push(t), dis[t] = 0;
        while( !que.empty() ) {
            int f = que.front(); que.pop();
            for(edge *p=adj[f];p;p=p->nxt)
                if( p->rev->cap > p->rev->flow )
                    if( dis[f] + 1 < dis[p->to] )
                        que.push(p->to), dis[p->to] = dis[f] + 1;
        }
        return !(dis[s] == INF);
    }
    int aug(int x, int tot) {
        if( x == t ) return tot;
        int sum = 0;
        for(edge *&p=cur[x];p;p=p->nxt) {
            if( p->cap > p->flow && dis[p->to] + 1 == dis[x] ) {
                int del = aug(p->to, min(p->cap - p->flow, tot - sum));
                sum += del, p->flow += del, p->rev->flow -= del;
                if( sum == tot ) break;
            }
        }
        return sum;
    }
    int max_flow(int _s, int _t) {
        int flow = 0; s = _s, t = _t;
        while( relabel() )
            flow += aug(s, INF);
        return flow;
    }
}G;
int P[MAXN + 5], Q[MAXN + 5];
bool tag[MAXN + 5];
int main() {
    int N, cnt; scanf("%d", &N), cnt = 2*N;
    for(int i=1;i<=N;i++)
        scanf("%d", &P[i]), P[i]++, tag[i] = false;
    for(int i=1;i<=N;i++)
        if( !tag[i] ) {
            int p = i; cnt++;
            do {
                tag[p] = true;
                p = P[p];
                G.addedge(cnt, p, INF, INF);
            }while( p != i );
        }
    for(int i=1;i<=N;i++)
        scanf("%d", &Q[i]), Q[i]++, tag[i] = false;
    for(int i=1;i<=N;i++)
        if( !tag[i] ) {
            int p = i; cnt++;
            do {
                tag[p] = true;
                p = Q[p];
                G.addedge(cnt, p + N, INF, INF);
            }while( p != i );
        }
    int s = 0, t = cnt + 1;
    for(int i=1;i<=N;i++) {
        if( i == P[i] && i == Q[i] && P[i] == Q[i] )// a = c = 1
            G.addedge(s, i, 1, 0), G.addedge(i, t, 1, 0);
        if( i == P[i] && i != Q[i] && P[i] != Q[i] )// b = 1
            G.addedge(s, i + N, 1, 0);
        if( i != P[i] && i == Q[i] && P[i] != Q[i] )// c = 1
            G.addedge(i, t, 1, 0);
        if( i != P[i] && i != Q[i] && P[i] == Q[i] )// e = f = 1
            G.addedge(i, i + N, 1, 1);
        if( i != P[i] && i != Q[i] && P[i] != Q[i] )// f = 1
            G.addedge(i, i + N, 1, 0);
    }//s -> i(a), s -> i+N(b), i -> t(c), i+N -> t(d), i+N -> i(e), i -> i+N(f)
    printf("%d\n", N - G.max_flow(s, t));
}

@details@

How water feeling than E F topic title ah. Is it my imagination it.

Guess you like

Origin www.cnblogs.com/Tiw-Air-OAO/p/11688690.html