codeforces CF85E Guard Towers 二分答案 二分图判定

本文解析了Codeforces题目GuardTowers的解题思路,通过二分查找和图论方法,寻找将塔楼分组以使同组内塔楼间曼哈顿距离最大值最小的策略,并计算满足条件的分组方案数量。

$ \rightarrow $ 戳我进CF原题

E. Guard Towers

time limit per test: 1.5 seconds
memory limit per test: 256 megabytes
input: standard input
outputstandard output

 

In a far away kingdom lives a very greedy king. To defend his land, he built $ n $ guard towers.
Apart from the towers the kingdom has two armies, each headed by a tyrannical and narcissistic general.
The generals can't stand each other, specifically, they will never let soldiers of two armies be present in one tower.
 
During defence operations to manage a guard tower a general has to send part of his army to that tower.
Each general asks some fee from the king for managing towers.
As they live in a really far away kingdom, each general evaluates his fee in the following weird manner:
he finds two remotest (the most distant) towers,
where the soldiers of his army are situated and asks for the fee equal to the distance.
Each tower is represented by a point on the plane with coordinates $ (x, y) $ ,
and the distance between two points with coordinates $ (x_1, y_1) $ and $ (x_2, y_2) $
is determined in this kingdom as $ |x_1 - x_2| + |y_1 - y_2| $ .
 
The greedy king was not exactly satisfied with such a requirement from the generals,
that's why he only agreed to pay one fee for two generals, equal to the maximum of two demanded fees.
However, the king is still green with greed, and among all the ways to arrange towers between armies,
he wants to find the cheapest one. Each tower should be occupied by soldiers of exactly one army.
 
He hired you for that. You should find the minimum amount of money that will be enough to pay the fees.
And as the king is also very scrupulous,
you should also count the number of arrangements that will cost the same amount of money.
As their number can be quite large, it is enough for the king to know it as a remainder from dividing by $ 10^9 + 7 $ .
 
Two arrangements are distinct if the sets of towers occupied by soldiers of the first general are distinct.
 

Input

The first line contains an integer $ n (2 ≤ n ≤ 5000), n $ is the number of guard towers.
Then follow $ n $ lines, each of which contains two integers $ x, y $
— the coordinates of the $ i $-th tower $ (0 ≤ x, y ≤ 5000) $ . No two towers are present at one point.
 
Pretest 6 is one of the maximal tests for this problem.
 

Output

Print on the first line the smallest possible amount of money that will be enough to pay fees to the generals.
 
Print on the second line the number of arrangements that can be carried out using the smallest possible fee.
This number should be calculated modulo $ 1000000007 (10^9 + 7) $ .
 

Examples

input1
 2
 0 0
 1 1
output1
 0
 2

input2
 4
 0 0
 0 1
 1 0
 1 1
output2
 1
 4

input3
 3
 0 0
 1000 1000
 5000 5000
output3
 2000
 2

 

Note

In the first example there are only two towers, the distance between which is equal to 2.
If we give both towers to one general, then we well have to pay 2 units of money.
If each general receives a tower to manage, to fee will be equal to 0.
That is the smallest possible fee. As you can easily see, we can obtain it in two ways.
 

题目大意

  • 已知 $ N $ 座塔的坐标, $ N \le 5000 $

  • 把它们分成两组,使得同组内的两座塔的曼哈顿距离最大值最小

  • 在此前提下求出有多少种分组方案 $ mod \quad 10^9 +7 $
     

题解

  • 二分答案 $ mid $

  • 曼哈顿距离 $ >mid $ 的点连边

  • 判定是否构成二分图

  • 方案数为 $ 2^{最终的二分图连通块数目} $
     

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 5005
#define ll long long
#define mod 1000000007
int col[N],mid,n,dis[N][N];
bool vis[N];
bool dfs(int u){
    vis[u]=1;
    for(int i=1;i<=n;++i)
        if(i!=u&&dis[u][i]>mid)
            if(!vis[i]){
                col[i]=col[u]^1;
                if(dfs(i)) return 1;
            }else if(col[u]==col[i]) return 1;
    return 0;
}
bool check(){
    memset(vis,0,sizeof(bool)*(n+1));
    for(int i=1;i<=n;++i)
        if(!vis[i]) if(dfs(i)) return 0;
    return 1;
}
int ans;
void dfs2(int u){
    vis[u]=1;
    for(int i=1;i<=n;++i){
        if(!vis[i]&&dis[u][i]>ans) dfs2(i);
    }
}
ll qpow(ll x,ll k){
    ll res=x*1ll; --k;
    while(k){
        if(k&1) res=res*x%mod;
        x=x*x%mod;
        k>>=1;
    }
    return res;
}
int cnt,x[N],y[N];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d %d",&x[i],&y[i]);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j){
            dis[i][j]=abs(x[i]-x[j])+abs(y[i]-y[j]);
        }
    int l=0,r=10000;
    while(l<=r){
        mid=l+r>>1;
        if(check()){ ans=mid; r=mid-1; }
        else l=mid+1;
    }
    memset(vis,0,sizeof(bool)*(n+1));
    printf("%d\n",ans);
    for(int i=1;i<=n;++i) if(!vis[i]){ ++cnt; dfs2(i); }
    printf("%lld",qpow(1ll*2,1ll*cnt));
    return 0;
}
/*
#         41511585 
When      2018-08-12 05:40:34 
Who       PotremZ 
Problem   E - Guard Towers 
Lang      GNU C++ 
Verdict   Accepted 
Time      358 ms 
Memory    98300 KB 
*/

转载于:https://www.cnblogs.com/PotremZ/p/CF85E.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值