2020 Multi-University Training Contest 4

Contents

概要

01 02 03 04 05 06 07 08 09 10 11 12
总体 ? ? ? ? ?
wzgy ?
csz ? ?
wh ? ?

比赛地址

2020 Multi-University Training Contest 4

题目

1007. Go Running

题目大意

在一条双向的轴上,有若干同学在跑步,每位同学的速度是固定的 1 单位长度/s。在 n 个时刻 t,位置 x 上将至少有一个人在跑步,但是方向不确定,仅能确定有人。问能确定最少有多少同学在跑步?

分析

转化成平面图,x 轴为时间轴,y 轴为跑步的轴,则每个同学有一个起点,在一条斜率为 1-1 的直线上运动。问题转化为,我们最少能用多少条斜率为 1-1 的直线覆盖全部的点。

由于斜线不好处理,我们考虑将坐标轴顺时针旋转 45 度。(x,y) 的坐标被映射到 (x + y, x – y)。问题转化为在直角坐标系中,最少用多少条平行于 x 轴或者平行于 y 轴的直线覆盖全部点。

将每条平行与 x 轴的线看成二分图左边的点,平行于 y 轴的线看成二分图右边的点;原图中的每个点,就对应二分图中的一条边。问题边转化为了二分图的最小点覆盖(选取最少的点,使得每条边均有至少一个点被选中)。由相关定理,二分图的最小点覆盖等于其最大匹配。跑 Dinic 即可。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 50;
const int M = 1e6 + 50;
const int INF = 1e9;

int head[N], tot = 1;
struct Edge {
    int nex, to, w;
}eg[M];
void addedge(int a, int b, int c) {
    eg[++tot] = (Edge){head[a], b, c};
    head[a] = tot;
}
void add(int a, int b, int c) {
    addedge(a, b, c);
    addedge(b, a, 0);
}

struct DINIC {
    queue<int> q;
    int n, S, T;
    int dep[N], cur[N];

    void init(int _n, int _S, int _T) {
        n = _n; S = _S; T = _T;
        memset(head, 0, sizeof(head));
        tot = 1;
    }

    int bfs() {
        while(!q.empty()) q.pop();
        memset(dep, 0, sizeof(dep)); dep[S] = 1;
        q.push(S);
        while(!q.empty()) {
            int now = q.front(); q.pop();
            for(int i = head[now]; i; i = eg[i].nex) {
                int to = eg[i].to;
                if(!dep[to] && eg[i].w) {
                    dep[to] = dep[now] + 1;
                    q.push(to);
                }
            }
        }
        return dep[T] > 0;
    }
    int dfs(int rt, int flow) {
        if(rt == T || !flow) return flow;
        for(int i = cur[rt]; i; i = eg[i].nex) {
            cur[rt] = i;
            int to = eg[i].to;
            if(dep[to] == dep[rt] + 1 && eg[i].w) {
                int f = dfs(to, min(flow, eg[i].w));
                if(f) {
                    eg[i].w -= f;
                    eg[i^1].w += f;
                    return f;
                }
            }
        }
        return 0;
    }
    long long Dinic() {
        long long ans = 0;
        while(bfs()) {
            for(int i = 1; i <= n; i++) cur[i] = head[i];
            while(int tmp = dfs(S, INF)) {
                ans += tmp;
            }
        }
        return ans;
    }

}dinic;

int n;
int x[N], y[N], a[N], b[N];

int main()
{
    int ; scanf("%d", &);
    while ($--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d%d", &x[i], &y[i]);
            a[i] = x[i] + y[i];
            b[i] = x[i] - y[i];
        }
        sort(a + 1, a + 1 + n);
        sort(b + 1, b + 1 + n);
        int ta = (int)(unique(a + 1, a + 1 + n) - a - 1);
        int tb = (int)(unique(b + 1, b + 1 + n) - b - 1);
        int S = ta + tb + 1, T = S + 1;
        dinic.init(T, S, T);
        for (int i = 1; i <= n; i++) {
            int idx = (int)(lower_bound(a + 1, a + 1 + ta, x[i] + y[i]) - a);
            int idy = (int)(lower_bound(b + 1, b + 1 + tb, x[i] - y[i]) - b);
            add(idx, idy + ta, 1);
        }
        for (int i = 1; i <= ta; i++) {
            add(S, i, 1);
        }
        for (int i = 1; i <= tb; i++) {
            add(i + ta, T, 1);
        }
        printf("%lld\n", dinic.Dinic());
    }
    return 0;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇