码迷,mamicode.com
首页 > 其他好文 > 详细

CFGym 101490J 题解

时间:2017-10-15 18:07:18      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:二分   老师   怎么办   连接   online   text   二分图匹配   很多   暴力   

一、题目链接

  http://codeforces.com/gym/101490

二、题面

  技术分享

三、题意

  给你n个点,代表学生所在位置,n个点,代表老师所在位置。每个学生分配一个老师。让你找出一个最小的学生到他的老师的距离(曼哈顿距离),使得其他学生到其老师的距离不超过这个距离。

四、思路

  一开始看到这个题,第一反应是N很小,可以考虑暴力搞。但是,压根没思路,暴力都不知道怎么暴。有个很朴素的思路,对第一个学生,枚举每一个老师,计算他和老师的距离,然后,对第二个以后的学生,dfs继续这么干。那这样的话,复杂度是O(100^100) >> O(2 ^ 100)。当时,我想到这个想法时,还和旁边的同学开了个玩笑,我说:我昨晚算了一下,从1循环到2^64次方,需要跑几年。假设普通计算机每秒做10E次操作,约等于10^9。2^64≈10^19,10^19/10^9=10^10(秒),一年也才3000W+秒,要跑300+年。

  好了,很明显,上面很Naive的想法肯定是不行的。那怎么办呢?其实这题不难往二分图的方向去想。因为比较裸。我后来看到有同学是用二分图匹配A的。我之前也敲过二分图匹配的题,但是,由于图论方面我没有做太多的训练,只会用用大家都会的图论板子而已。所以,虽然能想到二分图,但是,不知道该怎么去用。后来想到一个办法:二分枚举最大的距离,在原图的基础上删除所有距离比枚举值大的边,跑一遍dfs,如果能连通,则说明此枚举值有效。然而,GG……这个想法也不行。比如这个样例:

技术分享

  然后,我又想到另外一个方法:枚举每一个学生,看看所有的学生所能连接的老师有没有n个,有的话,当前二分的枚举值合法。然后,又找到这样的样例:

技术分享

  思路想到此了,既然这样不行,那我就把老师这边也来一次这样的,如果能连接的学生有n个,那么,这确实可以保证每个学生都和至少一个老师、每个老师都和至少一个学生有连接了。

至于存储能连接的老师有没有n个,这样的方法有很多。我使用的是bitset位存储。

五、源代码

  

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;
int n;
PLL stu[110], tea[110];
vector<int> g[2][110];

LL bas(LL x) {
    return x < 0 ? -x : x;
}

LL dis(PLL p1, PLL p2) {
    return bas(p1.first - p2.first) + bas(p1.second - p2.second);
}

bitset<110> match[2][110];
bool test(LL mid) {
    for(int i = 0; i < 110; ++i)g[0][i].clear(), g[1][i].clear();
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= n; ++j) {
            if(dis(stu[i], tea[j]) <= mid) {
                g[0][i].push_back(j);
                g[1][j].push_back(i);
            }
        }
    }
    bitset<110> res[2];
    res[0].reset(), res[1].reset();
    for(int i = 1; i <= n; ++i)match[0][i].reset(), match[1][i].reset();
    for(int k = 0; k < 2; ++k) {
        for(int i = 1; i <= n; ++i) {
            for(int j = 0, sz = g[k][i].size(); j < sz; ++j) {
                int adj = g[k][i][j];
                match[k][i].set(adj);
            }
            res[k] = res[k] | match[k][i];
        }
    }
    return res[0].count() == n && res[1].count() == n;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("Jinput.txt", "r", stdin);
#endif // ONLINE_JUDGE
    while(~scanf("%d", &n)) {
        for(int i = 1; i <= n; ++i)scanf("%lld%lld", &stu[i].first, &stu[i].second);
        for(int i = 1; i <= n; ++i)scanf("%lld%lld", &tea[i].first, &tea[i].second);
        LL low = -1, high = 1LL << 60, mid;
        while(low < high - 1) {
            mid = (high + low) / 2;
            if(test(mid))high = mid;
            else low = mid;
        }
        printf("%lld\n", high);
    }
    return 0;
}

 经验:由于习惯了int,这次的long long一不小心又用成了%d输入,然后,调试调了几十分钟,真不应该啊。

CFGym 101490J 题解

标签:二分   老师   怎么办   连接   online   text   二分图匹配   很多   暴力   

原文地址:http://www.cnblogs.com/565261641-fzh/p/7672593.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!