Codeforce 85E (二分答案+二分图染色)

本文探讨了如何使用二分图算法解决守塔问题,并通过代码实现了一个高效解决方案,包括邻接矩阵构建、二分搜索和图联通分量计数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题先处理出两个塔之间的距离保存在邻接矩阵里,然后二分答案,看看边权大于二分出的答案的边组成的图是不是二分图,是的话上界等于二分出的答案,否则下界等于二分出的答案,最后答案保存在上界里。然后算出边权答案的边组成的图的联通分量的个数cnt,方法数即为2cnt

AC代码(561ms):

#include <cassert>
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdalign>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#endif
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif
#define INF 1000000007
#define EPS 1e-10
#define myabs(x) ((x)>0?(x):-(x))
/*
	Problem: Guard Towers
	Source: Codeforces 85E
	Author: fts2001
*/
using namespace std;
int n,x[5005],y[5005],dist[5005][5005],vis[5005];
bool dfs(int c,int mid,int col){
	if(vis[c]!=-1)return col==vis[c];
	vis[c]=col;
	for(int i=0;i<n;i++){
		if(i!=c && mid<dist[c][i] && !dfs(i,mid,1-col))return false;
	}
	return true;
}
bool cor(int mid){
	memset(vis,-1,sizeof(vis));
	for(int i=0;i<n;i++){
		if(vis[i]==-1){
			if(!dfs(i,mid,0))return false;
		}
	}
	return true;
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>x[i]>>y[i];
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			dist[i][j]=myabs(x[i]-x[j])+myabs(y[i]-y[j]);
		}
	}
	int lb=-1,ub=10001,cnt=0,res=1;
	while(ub-lb>1){
		int mid=(lb+ub)/2;
		if(cor(mid))ub=mid;
		else lb=mid;
	}
	memset(vis,-1,sizeof(vis));
	for(int i=0;i<n;i++){
		if(vis[i]==-1){
			dfs(i,ub,0);
			cnt++;
		}
	}
	for(int i=0;i<cnt;i++){
		res=(res<<1)%INF;
	}
	cout<<ub<<'\n'<<res<<'\n';
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值