1. 程式人生 > 其它 >CF1519E Off by One

CF1519E Off by One

https://www.luogu.com.cn/problem/CF1519E

可以考慮連邊

\((\frac{a_i}{b_i}+1)-(\frac{c_i}{d_i})\)
\((\frac{a_i}{b_i})-(\frac{c_i}{d_i}+1)\)

然後跑最大匹配

code:

#include<bits/stdc++.h>
#define N 400050
#define ll long long
#define pii pair<ll, ll>
using namespace std;
map<pii, int> mp;
ll gcd(ll x, ll y) {
    return y? gcd(y, x % y) : x;
}
int tot;
int get(ll x, ll y) {
    ll d = gcd(x, y);
    x /= d, y /= d;
    pii o = make_pair(x, y);
    if(!mp[o]) mp[o] = ++ tot;
    return mp[o];
}
struct edge {
    int v, c, nxt;
} e[N << 1];
int p[N], eid;
void init() {
    memset(p, -1, sizeof p);
    eid = 0;
}
void insert(int u, int v, int c) { //printf("%d --> %d   %d\n", u, v, c);
    e[eid].v = v;
    e[eid].c = c;
    e[eid].nxt = p[u];
    p[u] = eid ++;
}
int vis[N], match[N], n;
vector<pii > ans;
void dfs(int u) {
    vis[u] = 1;
    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v, id = e[i].c;
        if(!id) continue;
        e[i].c = e[i ^ 1].c = 0;
        if(!vis[v]) dfs(v);

        if(match[v]) ans.push_back(make_pair(match[v], id)), match[v] = 0;
        else if(match[u]) ans.push_back(make_pair(match[u], id)), match[u] = 0;
        else match[u] = id;
    }
}
int main() {
    init();
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) {
        int a, b, c, d;
        scanf("%d%d%d%d", &a, &b, &c, &d);
        int u = get(1ll * (a + b) * d, 1ll * b * c);
        int v = get(1ll * a * d, 1ll * (c + d) * b);
        insert(u, v, i), insert(v, u, i);
    }

    for(int i = 1; i <= tot; i ++) if(!vis[i]) dfs(i);
    printf("%d\n", (int)ans.size());
    for(auto i : ans) 
        printf("%d %d\n", i.first, i.second);
    return 0;
}