其他分享
首页 > 其他分享> > cf1419F Rain of Fire

cf1419F Rain of Fire

作者:互联网

cf1419F Rain of Fire

https://codeforces.com/contest/1419/problem/F

写了一个二分+并查集的做法。

首先对于平行x轴或者y轴的点对,可以连边建图。

先不考虑添一个点的情况:

​ 那么题目要求的就是:使所有点连通,最大边权的最小值。

​ 因为所有点连通,并且点可以重复经过,所以求生成树就行。 那么题目转换成 求最大边权最小的生成树,跑Kruskal算法就可以得到。

考虑添点的情况:

  1. 首先把无解的情况判掉,如果原图连通块个数大于2,添一个点显然不够用了,无解。

  2. 考虑联通块小于等于2的情况:

二分答案w,可以先把边权小于w的边都用上。再添一个点让所有点连到一起。

考虑添的点的可能位置:要么是原图所有边的中点,要么是形如(x[i],y[j]),(x[j],y[i])的点(如果(x[i],y[i]),(x[j],y[j])是题目给的点)。有O(n^2)个。

枚举这些位置,在这类位置添点,可以把这个位置上下左右距离最近的点连起来(要判一下距离是否小于等于w)。

实现起来的话要卡卡常,比如:

总复杂度是 logw * n^2 的。

#include <bits/stdc++.h>
using namespace std;

#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef long long ll;
typedef double db;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef pair<long long,int> PLI;
typedef pair<long long,long long> PLL;
const ll mod=1000000007;
//mt19937 mrand(random_device{}());
//int rnd(int x) { return mrand() % x;}
//__builtin_popcount(n)
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

int n;
int x[1006],y[1006];

struct Dsu
{
int fa[1006];
void init(int n)
{
for(int i=1;i<=n;i++)fa[i]=i;
}
int myfind(int x){return x==fa[x]?x:fa[x]=myfind(fa[x]);}
void unit(int x,int y)
{
int s=myfind(x),t=myfind(y);
fa[s]=t;
}
}dsu1,dsu2;

struct Edge
{
int x,y,w;
bool operator<(const Edge&rhs)const
{
return w<rhs.w;
}
};
vector<Edge>E;

vector<PII>vec[3],node;
VI ID;
set<int>Set;
map<PII,int>Map;
VI V[4000066],VVV;

PII solve(const vector<Edge>&E,int w)
{
int last=0,now=0;
dsu2.init(n);
for(int i=0;i<SZ(E)&&E[i].w<=w;i++)
{
auto e=E[i];
int s=dsu2.myfind(e.x);
int t=dsu2.myfind(e.y);
if(s==t)continue;
dsu2.unit(s,t);
last=now,now=e.w;
}
return mp(last,now);
}

bool judge(int w)
{
//EE.clear();
//for(int i=0;i<SZ(E)&&E[i].w<=w;i++)EE.pb(E[i]);
solve(E,w);
Set.clear();
for(int i=1;i<=n;i++)Set.insert(dsu2.myfind(i));
// for(int i=1;i<=n;i++)printf("%d : %d\n",i,dsu2.myfind(i));
if(SZ(Set)==1)return true;
int need=SZ(Set);
for(int i=0;i<SZ(node);i++)
{
auto poi=node[i];
int id=ID[i];
Set.clear();
//printf("%d %d : ",poi.fi,poi.se);
for(auto i:V[id])
{
int val=max(abs(x[i]-poi.fi),abs(y[i]-poi.se));
if(val<=w)
Set.insert(dsu2.myfind(i));
//printf(" ( %d , %d )",x[i],y[i]);
}//puts("");
if(SZ(Set)!=need)continue;
return true;
}
return false;
}

bool vis[1006];

int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]);
dsu1.init(n);
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(x[i]==x[j]||y[i]==y[j])
dsu1.unit(i,j);
}
}
for(int i=1;i<=n;i++)Set.insert(dsu1.myfind(i));

if(SZ(Set)>2){puts("-1");return 0;}

int tot=0;

for(int i=1;i<=n;i++)
{
if(vis[i])continue;
VVV.clear();
VVV.pb(i);
for(int j=i+1;j<=n;j++)
{
if(x[i]==x[j])
{
vis[j]=true;
VVV.pb(j);
}
}
sort(all(VVV),[&](int lhs,int rhs)
{
return y[lhs]<y[rhs];
});
int X=x[i],Y;
for(int i=0;i<SZ(VVV)-1;i++)
{
E.pb(Edge{VVV[i],VVV[i+1],y[VVV[i+1]]-y[VVV[i]]});

if(SZ(Set)==1)
{
Y=(y[VVV[i+1]]+y[VVV[i]])/2;
if(!Map.count(mp(X,Y)))Map[mp(X,Y)]=++tot;
int id=Map[mp(X,Y)];
V[id].pb(VVV[i]);V[id].pb(VVV[i+1]);
node.eb(X,Y);
}
}
}

memset(vis,0,sizeof(vis));

for(int i=1;i<=n;i++)
{
if(vis[i])continue;
VVV.clear();
VVV.pb(i);
for(int j=i+1;j<=n;j++)
{
if(y[i]==y[j])
{
vis[j]=true;
VVV.pb(j);
}
}
sort(all(VVV),[&](int lhs,int rhs)
{
return x[lhs]<x[rhs];
});
int X,Y=y[i];
for(int i=0;i<SZ(VVV)-1;i++)
{
E.pb(Edge{VVV[i],VVV[i+1],x[VVV[i+1]]-x[VVV[i]]});

if(SZ(Set)==1)
{
X=(x[VVV[i+1]]+x[VVV[i]])/2;
if(!Map.count(mp(X,Y)))Map[mp(X,Y)]=++tot;
int id=Map[mp(X,Y)];
V[id].pb(VVV[i]);V[id].pb(VVV[i+1]);
node.eb(X,Y);
}
}
}

for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(x[i]==x[j]||y[i]==y[j])
{
//E.pb(Edge{i,j,max(abs(x[i]-x[j]),abs(y[i]-y[j]))});
}
else
{
int X=x[i],Y=y[j];
if(!Map.count(mp(X,Y)))Map[mp(X,Y)]=++tot;
int id=Map[mp(X,Y)];
V[id].pb(i);V[id].pb(j);


X=x[j],Y=y[i];
if(!Map.count(mp(X,Y)))Map[mp(X,Y)]=++tot;
id=Map[mp(X,Y)];
V[id].pb(i);V[id].pb(j);

node.eb(x[i],y[j]);
node.eb(x[j],y[i]);
}
}
}
sort(all(E));
sort(all(node));
node.resize(unique(all(node))-node.begin());
for(int i=1;i<=tot;i++)
{
sort(all(V[i]));
V[i].resize(unique(all(V[i]))-V[i].begin());
}

for(auto pii:node)ID.pb(Map[pii]);
//if(judge(2))puts("YES");
//return 0;
int l=0,r=2e9;
while(l<r)
{
//printf("%d %d__\n",l,r);
int mid=(0ll+l+r)>>1;///
if(judge(mid))r=mid;
else l=mid+1;
}
printf("%d\n",l);

return 0;

}

/*

4
1 0
0 1
-1 0
0 -1

2
1000000000 1000000000
-1000000000 -1000000000


*/

标签:typedef,Fire,res,ll,Rain,int,1000000000,cf1419F,define
来源: https://www.cnblogs.com/w-57/p/14660735.html