zoukankan      html  css  js  c++  java
  • 2020牛客多校第八场I-Interseting Computer Game

    https://ac.nowcoder.com/acm/contest/5673/I

    题意

    给了两个数组:({a_1, a_2, dots a_n}, {b_1, b_2, dots b_n})
    第i步可以从(a_i)(b_i)中选择一个数。
    求最后选出的数中,不同的数要最多

    题解

    正解是把每个点对((a_i,b_i))当成一个图中的一条边,如果一个联通分量中有环,则所有点都可以取到,若为树形结构,那么只能取到k-1个点,用并查集判断有没有环即可

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double db;
    struct READ {
        inline char read() {
        #ifdef Artoriax
            return getchar();
        #endif
            const int LEN = 1 << 18 | 1;
            static char buf[LEN], *s, *t;
            return (s == t) && (t = (s = buf) + fread(buf, 1, LEN, stdin)), s == t ? -1 : *s++;
        }
        inline READ & operator >> (char *s) {
            char ch;
            while (isspace(ch = read()) && ~ch);
            while (!isspace(ch) && ~ch) *s++ = ch, ch = read(); *s = '';
            return *this;
        }
        inline READ & operator >> (string &s) {
            s = ""; char ch;
            while (isspace(ch = read()) && ~ch);
            while (!isspace(ch) && ~ch) s += ch, ch = read();
            return *this;
        }
        template <typename _Tp> inline READ & operator >> (_Tp&x) {
            char ch, flag;
            for(ch = read(),flag = 0; !isdigit(ch) && ~ch; ch = read()) flag |= ch == '-';
            for(x = 0; isdigit(ch); ch = read()) x = x * 10 + (ch ^ '0');
            flag && (x = -x);
            return *this;
        }
    } in;
    
    const int N = 2e5 + 50;
    int f[N];
    int a[N], b[N], lis[N], vis[N];
    int find(int x) {
        return f[x] == x ? x : f[x] = find(f[x]);
    }
    int main() {
        int _; in >> _;
        for (int t = 1; t <= _; t++) {
            int n; in >> n;
            for (int i = 1; i <= n; i++) {
                in >> a[i] >> b[i];
                lis[i*2-1] = a[i], lis[i*2] = b[i];
            }
            sort(lis + 1, lis + 2 * n + 1);
            int m = unique(lis + 1, lis + 2 * n + 1) - lis - 1;
            for (int i = 1; i <= m; i++) f[i] = i, vis[i] = 0;
            for (int i = 1; i <= n; i++) {
                a[i] = lower_bound(lis + 1, lis + m + 1, a[i]) - lis;
                b[i] = lower_bound(lis + 1, lis + m + 1, b[i]) - lis;
                int x = find(a[i]), y = find(b[i]);
                if (x == y) vis[x] = vis[y] = 1;
                else {
                    f[y] = x;
                    if (vis[y]) vis[x] = 1;
                }
            }
            int ans = m;
            for (int i = 1; i <= m; i++) {
                f[i] = find(f[i]);
                if (f[i] == i && !vis[i]) ans--;
            }
            printf("Case #%d: %d
    ", t, ans);
        }
        return 0;
    }
    

    比赛的时候是直接用二分图匹配求解的,用isap卡过去了,二分图的建立方式即i向a[i],b[i]分别连边

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    struct READ {
        inline char read() {
        #ifdef _WIN32
            return getchar();
        #endif
            static const int IN_LEN = 1 << 18 | 1;
            static char buf[IN_LEN], *s, *t;
            return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
        }
        template <typename _Tp> inline READ & operator >> (_Tp&x) {
            static char c11, boo;
            for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
                if(c11 == -1) return *this;
                boo |= c11 == '-';
            }
            for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
            boo && (x = -x);
            return *this;
        }
    } in;
     
    const int inf = 0x3f3f3f3f;
    const int N = 3e5 + 50;
    struct node {
        int v, cap, flow, nxt;
        node () {}
        node (int v, int cap, int flow, int nxt): v(v), cap(cap), flow(flow), nxt(nxt) {}
    } edge[N * 10];
    int head[N], tot;
    void init() {
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    int dep[N];
    void adde(int u, int v, int w) {
        edge[tot] = node(v, w, 0, head[u]);
        head[u] = tot++;
        edge[tot] = node(u, 0, 0, head[v]);
        head[v] = tot++;
    }
    int gap[N], cur[N];
    void bfs(int s, int t) {
        memset(dep, -1, sizeof(dep));
        memset(gap, 0, sizeof(gap));
        gap[0] = 1;
        queue<int> q;
        dep[t] = 0;
        q.push(t);
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int i = head[u]; ~i; i = edge[i].nxt) {
                int v = edge[i].v;
                if (dep[v] != -1) continue;
                q.push(v);
                dep[v] = dep[u] + 1;
                gap[dep[v]]++;
            }
        }
    }
    int S[N];
    int sap(int s, int t, int n) {
        bfs(s, t);
        memcpy(cur, head, sizeof(head));
        int top = 0;
        int u = s;
        int ans = 0;
        while (dep[s] < n) {
            if (u == t) {
                int minn = inf;
                int inser;
                for (int i = 0; i < top; i++) {
                    if (minn > edge[S[i]].cap - edge[S[i]].flow) {
                        minn = edge[S[i]].cap - edge[S[i]].flow;
                        inser = i;
                    }
                }
                for (int i = 0; i < top; i++) {
                    edge[S[i]].flow += minn;
                    edge[S[i] ^ 1].flow -= minn;
                }
                ans += minn;
                top = inser;
                u = edge[S[top] ^ 1].v;
                continue;
            }
            bool flag = false;
            int v;
            for (int i = cur[u]; ~i; i = edge[i].nxt) {
                v = edge[i].v;
                if (edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u]) {
                    flag = true;
                    cur[u] = i;
                    break;
                }
            }
            if (flag) {
                S[top++] = cur[u];
                u = v;
                continue;
            }
            int minn = n;
            for (int i = head[u]; ~i; i = edge[i].nxt) {
                if (edge[i].cap - edge[i].flow && dep[edge[i].v] < minn) {
                    minn = dep[edge[i].v];
                    cur[u] = i;
                }
            }
            gap[dep[u]]--;
            if (!gap[dep[u]]) return ans;
            dep[u] = minn + 1;
            gap[dep[u]]++;
            if (u != s) u = edge[S[--top] ^ 1].v;
        }
        return ans;
    }
    int main() {
        int t; in >> t;
        int cse = 0;
        while (t--) {
            init();
            int n; in >> n;
            map<int, int> mp;
            int cnt = 0;
            for (int i = 1; i <= n; i++) {
                int u, v;
                in >> u >> v;
                if (!mp.count(u)) mp[u] = ++cnt;
                if (!mp.count(v)) mp[v] = ++cnt;
                u = mp[u];
                v = mp[v];
                adde(i, u + n, 1);
                adde(i, v + n, 1);
            }
            for (int i = 1; i <= n; i++) {
                adde(0, i, 1);
            }
            for (int i = 1; i <= cnt; i++) {
                adde(i + n, n + cnt + 1, 1);
            }
            printf("Case #%d: %d
    ", ++cse, sap(0, n + cnt + 1, n + cnt + 1));
        }
        return 0;
    }
    
  • 相关阅读:
    HTML5程序设计web workers API 学习笔记
    HTML5 拖拽API 学习笔记
    2013.03.23这天的一点感触和计划
    localStorage实现返回到原位置以及pjax的反思
    HTML5 localStorage浅谈
    javascript学习之函数对象简介
    display:-webkit-box
    由登录表单的用户体验细节说开
    前端和用户体验
    Laravel实践step1,一个简单的crud
  • 原文地址:https://www.cnblogs.com/artoriax/p/13632336.html
Copyright © 2011-2022 走看看