hdu 5740(构造,KM)

来源:互联网 发布:ps二维码源码 编辑:程序博客网 时间:2024/05/19 18:11

这里写图片描述

#include <bits/stdc++.h>using namespace std;#define LL long long#define pii pair<int, int>#define MP make_pair#define ls i << 1#define rs ls | 1#define md (ll + rr >> 1)#define inf 0x3f3f3f3f#define mod 1000000007#define N 520#define M 500020int getint(){    int ret = 0; char ch = getchar();    while(ch < '0' || ch > '9') ch = getchar();    while(ch >= '0' && ch <= '9')        ret = ret * 10 + ch - '0', ch = getchar();    return ret;}int n, m, ans;int fst[N], vv[M], nxt[M], e;int c1, c2, sz, col[N];int dis[N][N], pre[N][N];char s[N];bool vis[N];vector<int> node;void init(){    memset(fst, -1, sizeof fst); e = 0;}void add(int u, int v){    vv[e] = v, nxt[e] = fst[u], fst[u] = e++;}bool bin_color(int u){    c1 += col[u] == 1;    c2 += s[u] == '1';    ++sz;    for(int i = fst[u]; ~i; i = nxt[i]){        int v = vv[i];        if(!col[v]){            col[v] = 3 - col[u];            if(!bin_color(v))                return 0;        }        else if(col[v] == col[u]) return 0;    }    return 1;}void bfs(int s, int d[], int pre[]){    queue<int> q;    q.push(s);    d[s] = 0;    pre[s] = s;    while(!q.empty()){        int u = q.front(); q.pop();        for(int i = fst[u]; ~i; i = nxt[i]){            int v = vv[i];            if(d[v] > d[u] + 1){                d[v] = d[u] + 1;                pre[v] = u;                q.push(v);            }        }    }}bool check(){    for(int i = 1; i <= n; ++i){        if(!col[i]){            col[i] = 1;            c1 = c2 = sz = 0;            if(!bin_color(i))                 return 0;            if(min(sz - c1, c1) != min(sz - c2, c2)) return 0;        }    }    return 1;}void mark(int u){    vis[u] = 1;    node.push_back(u);    for(int i = fst[u]; ~i; i = nxt[i]){        int v = vv[i];        if(!vis[v])            mark(v);    }}int nu, val[N][N];int lx[N], ly[N], link[N];bool visx[N], visy[N];vector<int> match[2];int slack[N];bool dfs(int u){    visx[u] = 1;    for(int i = 1; i <= nu; ++i){        if(visy[i]) continue;        int t = lx[u] + ly[i] - val[u][i];        if(t == 0){            visy[i] = 1;            if(link[i] == -1 || dfs(link[i])){                link[i] = u;                return 1;            }        }        else if(slack[i] > t)            slack[i] = t;    }    return 0;}int km(){    memset(ly, 0, sizeof ly);    for(int i = 1; i <= nu; ++i){        lx[i] = -inf;        for(int j = 1; j <= nu; ++j)            lx[i] = max(lx[i], val[i][j]);    }    memset(link, -1, sizeof link);    for(int i = 1; i <= nu; ++i){        memset(slack, 0x3f, sizeof slack);        while(1){            memset(visx, 0, sizeof visx);            memset(visy, 0, sizeof visy);            if(dfs(i)) break;            int d = inf;            for(int i = 1; i <= nu; ++i)                if(!visy[i] && slack[i] < d)                    d = slack[i];            for(int i = 1; i <= nu; ++i)                if(visx[i])                    lx[i] -= d;            for(int i = 1; i <= nu; ++i){                if(visy[i])                    ly[i] += d;                else                    slack[i] -= d;            }        }    }    int ret = 0;    int cnt = 0;    for(int i = 1; i <= nu; ++i){        if(link[i] != -1 && val[link[i]][i] != -inf)                ++cnt, ret += val[link[i]][i];    }    if(cnt < nu) return -1;    return -ret;}vector<int> ll[2];int gao(int w){    ll[0].clear(); ll[1].clear();    c1 = c2 = 0;    for(int i = 0; i < node.size(); ++i){        int v = node[i];        c1 += col[v] == 2;        c2 += s[v] == '1';        if(s[v] - '0' != col[v] - 1){            ll[s[v]-'0'].push_back(v);        }    }    if(c1 != c2) return inf;    nu = ll[0].size();    for(int i = 0; i < nu; ++i)        for(int j = 0; j < nu; ++j)            val[i+1][j+1] = -dis[ll[0][i]][ll[1][j]];    int ret = km();    for(int i = 1; i <= nu; ++i){        int v = ll[1][i-1];        match[w].push_back(v);        match[w].push_back(ll[0][link[i]-1]);    }    return ret;}vector<pii > ff, f;void get(int u, int v){    int t = v;    while(v != u){        t = v;        ff.clear();        while(t != u && s[t] == s[v])            ff.push_back(MP(t, pre[u][t])), t = pre[u][t];        for(int i = ff.size() - 1; i >= 0; --i){            swap(s[ff[i].first], s[ff[i].second]);            f.push_back(ff[i]);        }        v = t;    }}void build(vector<int> g){    for(int i = 0; i < g.size(); i += 2){        int u = g[i], v = g[i+1];        get(u, v);    }}int main(){    int cas;    scanf("%d", &cas);    while(cas--){        scanf("%d%d", &n, &m);        scanf("%s", s + 1);        init();        for(int i = 1; i <= m; ++i){            int u, v;            u = getint(), v = getint();            add(u, v), add(v, u);        }        for(int i = 1; i <= n; ++i)            col[i] = vis[i] = 0;        if(!check()){            puts("-1"); continue;        }        for(int i = 0; i <= n; ++i)            for(int j = 0; j <= n; ++j)                dis[i][j] = inf;        for(int i = 1; i <= n; ++i)            bfs(i, dis[i], pre[i]);        ans = 0;        f.clear();        for(int i = 1; i <= n; ++i){            if(!vis[i]){                match[0].clear();                match[1].clear();                node.clear();                mark(i);                if(node.size() == 1) continue;                int t1 = gao(0);                for(int j = 0; j < node.size(); ++j) col[node[j]] = 3 - col[node[j]];                int t2 = gao(1);                if(t1 <= t2){                    ans += t1;                    build(match[0]);                }                else{                    ans += t2;                    build(match[1]);                }            }        }        printf("%d\n", ans);        for(int i = 0; i < f.size(); ++i)            printf("%d %d\n", f[i].first, f[i].second);    }    return 0;}
0 0
原创粉丝点击