G:网络流

题意:
将题意简单化
意思是给你一个数组 a 已经填出了奇数位置的值,
要求你填完偶数位置,填入偶数位置的值只能是属于 [0,n - 1] 且 不在奇数位置出现
填数的要求如下
1: 任意两个相邻位置的数的二进制有且仅有一位不同
2: 第 n 位 只需要保证与 n - 1 位 有一个不同即可
保证有解

解析: 半天看不懂题,看懂题之后就知道怎么做了
将限制转换成为建边
首先对于网络流的题应该 先规划出 源点S 汇点T 以及中间点的范围;
本题 将 a 数组中能够出现的数字 [0, n - 1], 以及 (a数组中的下标)[n, 2 * n] 设为中间点 
S 设为 n, T 设为 2 * n;

因为对于我们填入的偶数坑,实际上是有两个限制的,要同时满足 跟两边的奇数坑里的数只有一个二进制位不同,
那么手动模拟一下情况可以知道,
当 a[i] 与 a[i + 2] 在某个二进制位相同时 a[i + 1] 在这一位也只能取相同
当他们在当前二进制位不同时 a[i + 1] 可以取反;
如此我们可以建一条S 向 n + i + 1 的边 容量为 1
同时对 当前位置可填入的值 res 建一条 n + i + 1 向 res 的边
同时 res 要向 T 建一条边;
注意每个 res 只能向 T 建一条边,因为实际上这个 res 只能被用一次, 我们用set 去重即可
特殊的 对于 n 这个位置而言 他只有 n - 1 一个约束条件 所以随便改,只要值小于 n 都可以建边
最后套板子;
#include<bits/stdc++.h>
#define ll long long
#define int long long
#define x first
#define y second
using namespace std;
const int maxN = 2e5 + 10;
const int maxM = 2e5 + 10;
const int INF = 1e18;
const int mod = 998244353;
inline ll read()
{
    ll ans=0,f=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')f^=(ch=='-'),ch=getchar();
    while(ch>='0'&&ch<='9')ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return f?-ans:ans;
}
int m,n,S,T;
struct edge
{
    int nxt,to,f;
}e[maxM << 1];
int head[maxN << 1],idx;
void add(int u,int v,int w)
{
    e[idx] = {head[u], v, w}; head[u] = idx++;
}
int d[maxN], cur[maxN], a[maxN];
bool bfs()
{
    queue<int>q;
    for(int i = 0 ; i <= T ; i++) d[i] = -1;
    q.push(S),cur[S] = head[S];
    d[S] = 0;
    while(!q.empty())
    {
        int t = q.front();
        q.pop();
        for(int i = head[t] ; ~i ; i = e[i].nxt)
        {
            int ver = e[i].to;
            if(d[ver] == -1 && e[i].f)
            {
                d[ver] = d[t] + 1;
                cur[ver] = head[ver];
                if(ver == T) return true;
                q.push(ver); 
            }
        }
    }
    return false;
}
int find(int u, int limit)
{
    if(u == T) return limit;
    int flow = 0;
    for(int i = head[u] ; ~i && flow < limit ; i = e[i].nxt)
    {
        cur[u] = i;
        int ver = e[i].to;
        if(d[ver] == d[u] + 1 && e[i].f)
        {
            int t = find(ver, min(e[i].f, limit - flow));
            if(!t) d[ver] = -1;
            e[i].f -= t;
            e[i ^ 1].f += t;
            flow += t;
        }
    }
    return flow;

}
void dinic()
{
    int r = 0,flow;
    while(bfs())
        while((flow = find(S,INF)) && flow)
            r += flow;
    for(int i = 0 ; i < idx ; i += 2)
    {
        if(!e[i].f && e[i].to < n && e[i ^ 1].to > n)
            a[e[i ^ 1].to - n] = e[i].to;
    }
    for(int i = 1 ; i <= n ; i++) printf("%lld ",a[i]);
}
signed main()
{
    memset(head, -1, sizeof head);
    n = read();
    S = n, T = n + n + 1;
    for(int i = 1 ; i <= n ; i += 2) a[i] = read();
    int res = 0;
    set<pair<int,int>>G;
    for(int i = 1 ; i < n - 1 ; i += 2)
    {
        for(int j = 17 ; j >= 0 ; j--)
        {
            if((a[i] >> j & 1) == (a[i + 2] >> j & 1)) continue;
            else 
            {
                if(a[i] >> j & 1) 
                {
                    res = a[i + 2] + (1ll << j);
                    if(G.find({S, n + i + 1}) == G.end())
                    {
                        G.insert({S,n + i + 1});
                        add(S, n + i + 1, 1);
                        add(n + i + 1, S, 0);
                    }
                    add(n + i + 1, res, 1);
                    add(res, n + i + 1, 0);
                    if(G.find({T, res}) == G.end())
                    {
                        G.insert({T, res});
                        add(res, T, 1);
                        add(T, res, 0);
                    }
                }
                else 
                {
                    res = a[i + 2] - (1ll << j);
                    if(G.find({S, n + i + 1}) == G.end())
                    {
                        G.insert({S,n + i + 1});
                        add(S, n + i + 1, 1);
                        add(n + i + 1, S, 0);
                    }
                    add(n + i + 1, res, 1);
                    add(res, n + i + 1, 0);
                    if(G.find({T, res}) == G.end())
                    {
                        G.insert({T, res});
                        add(res, T, 1);
                        add(T, res, 0);
                    }
                }
            }
        }
    }
    res = 0;
    add(S, 2ll * n, 1);
    add(2ll * n, S, 0);
    for(int i = 17 ; i >= 0 ; i--)
    {
        if(a[n - 1] >> i & 1)
        {
            res = a[n - 1];
            res -= (1ll << i);
            if(res > n - 1) continue;
            add(2 * n, res, 1);
            add(res, 2 * n, 0);
            if(G.find({T, res}) == G.end())
            {
                G.insert({T, res});
                add(res, T, 1);
                add(T, res, 0);
            }
        }
        else 
        {
            res = a[n - 1];
            res += (1ll << i);
            if(res > n - 1) continue;
            add(2 * n, res, 1);
            add(res, 2 * n, 0);
            if(G.find({T, res}) == G.end())
            {
                G.insert({T, res});
                add(res, T, 1);
                add(T, res, 0);
            }
        }
    }
    dinic();
    system("pause");
    return 0;
}