链接
https://nanti.jisuanke.com/t/40895
题解
首先二分
然后问题就是怎么
c
h
e
c
k
check
check
建图,对每个
(
x
i
,
y
i
)
(x_i,y_i)
(xi,yi)建两个点,一个点表示它横着发射激光,一个点表示它竖着发射激光
如果点
(
x
i
,
y
i
)
(x_i,y_i)
(xi,yi)横着就会导致
(
x
j
,
y
j
)
(x_j,y_j)
(xj,yj)必须竖着,那就从横
i
_i
i到竖
j
_j
j连一条边
最后看下对于每个
i
i
i,横
i
_i
i和竖
i
_i
i如果在同一个强连通分量里,那就不行,否则就可以
代码
#include <bits/stdc++.h>
#define maxn 40010
#define maxe 10000010
#define linf (1ll<<60)
#define iinf 0x3f3f3f3f
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
int N, x[maxn], y[maxn];
struct Graph
{
int etot, head[maxn], to[maxe], next[maxe];
void clear(int N)
{
for(int i=1;i<=N;i++)head[i]=0;
etot=0;
}
void adde(int a, int b, int c=0){to[++etot]=b;next[etot]=head[a];head[a]=etot;}
}G;
struct Trajan_SCC
{
int dfn[maxn], low[maxn], vis[maxn], scc[maxn], tim, scc_cnt;
stack<int> s;
void clear(int n)
{
for(int i=1;i<=n;i++)vis[i]=0;
tim=scc_cnt=0;
}
void dfs(Graph &G, int pos)
{
int p;
dfn[pos]=low[pos]=++tim;
s.emplace(pos);
vis[pos]=1;
for(p=G.head[pos];p;p=G.next[p])
{
if(vis[G.to[p]]==0)dfs(G,G.to[p]);
if(vis[G.to[p]]==1)low[pos]=min(low[pos],low[G.to[p]]);
}
if(dfn[pos]==low[pos])
{
int x;
scc_cnt++;
do
{
x=s.top(), s.pop();
scc[x]=scc_cnt;
vis[x]=2;
}
while(x!=pos);
}
}
void run(Graph &G, int n)
{
for(int i=1;i<=n;i++)if(!vis[i])dfs(G,i);
}
}tarjan;
vector<int> row[1000010], col[1000010];
bool check(int P)
{
int i, j;
G.clear(2*N);
tarjan.clear(2*N);
for(i=0;i<=1000000;i++)
for(auto a:row[i])for(auto b:row[i])
if(a!=b and abs(y[a]-y[b])<=2*P)G.adde(a+N,b);
for(i=0;i<=1000000;i++)
for(auto a:col[i])for(auto b:col[i])
if(a!=b and abs(x[a]-x[b])<=2*P)G.adde(a,b+N);
tarjan.run(G,2*N);
for(i=1;i<=N;i++)if(tarjan.scc[i]==tarjan.scc[N+i])return false;
return true;
}
int main()
{
int i, j, l, r, mid;
cin>>N;
for(i=1;i<=N;i++)
{
cin>>x[i]>>y[i];
row[x[i]].emplace_back(i);
col[y[i]].emplace_back(i);
}
l=0, r=1000000;
while(l<r)
{
mid=(l+r+1)>>1;
if(check(mid))l=mid;
else r=mid-1;
}
if(l==1000000)cout<<"UNLIMITED";
else cout<<l;
return 0;
}