扩散(洛谷-P1661)
題目描述
一個(gè)點(diǎn)每過(guò)一個(gè)單位時(shí)間就會(huì)向四個(gè)方向擴(kuò)散一個(gè)距離,如圖。
兩個(gè)點(diǎn)a、b連通,記作e(a,b),當(dāng)且僅當(dāng)a、b的擴(kuò)散區(qū)域有公共部分。連通塊的定義是塊內(nèi)的任意兩個(gè)點(diǎn)u、v都必定存在路徑e(u,a0),e(a0,a1),…,e(ak,v)。給定平面上的n給點(diǎn),問(wèn)最早什么時(shí)刻它們形成一個(gè)連通塊。
輸入輸出格式
輸入格式:
第一行一個(gè)數(shù)n,以下n行,每行一個(gè)點(diǎn)坐標(biāo)。
對(duì)于20%的數(shù)據(jù),滿(mǎn)足1≤N≤5; 1≤X[i],Y[i]≤50;
對(duì)于100%的數(shù)據(jù),滿(mǎn)足1≤N≤50; 1≤X[i],Y[i]≤10^9。
輸出格式:
一個(gè)數(shù),表示最早的時(shí)刻所有點(diǎn)形成連通塊。
輸入輸出樣例
輸入樣例#1:
2
0 0
5 5
輸出樣例#1:
5
思路:任意兩點(diǎn)的距離為兩點(diǎn)間的曼哈頓距離,假設(shè)任意兩點(diǎn)間有邊,那么問(wèn)題就轉(zhuǎn)換為求所有點(diǎn)構(gòu)成的最小生成樹(shù)中最長(zhǎng)的邊+1 再除以 2,因此利用 Kruskal 求出最小生成樹(shù),找到其中最長(zhǎng)邊即可
源代碼
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<utility> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #include<bitset> #define PI acos(-1.0) #define INF 0x3f3f3f3f #define LL long long #define Pair pair<int,int> const double EPS = 1E-10; const int MOD = 1E9+7; const int N = 1000000+5; const int dx[] = {-1,1,0,0,-1,-1,1,1}; const int dy[] = {0,0,-1,1,-1,1,-1,1}; using namespace std; struct Edge{int x,y;int dis;Edge(){}Edge(int x,int y,int dis):x(x),y(y),dis(dis){}bool operator < (const Edge &rhs)const{return dis<rhs.dis;} }edge[N]; struct Node{int x,y;Node(){}Node(int x,int y):x(x),y(y){} }node[N]; int tot; int father[N]; int getDis(int i,int j){return abs(node[i].x-node[j].x)+abs(node[i].y-node[j].y); } int Find(int x){return father[x]==x?x:father[x]=Find(father[x]); } int Kruskal(int n){for(int i=1;i<=n;i++)father[i]=i;int num=0;int res=-INF;for(int i=1;i<=tot;i++){int x=edge[i].x;int y=edge[i].y;x=Find(x);y=Find(y);if(x!=y){res=max(res,edge[i].dis);num++;father[x]=y;}if(num==n)break;}return res; } int main(){int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d%d",&node[i].x,&node[i].y);for(int i=1;i<n;i++){for(int j=i+1;j<=n;j++){edge[++tot].x=i;edge[tot].y=j;edge[tot].dis=getDis(i,j);}}sort(edge+1,edge+1+tot);int res=Kruskal(n);printf("%d\n",(res+1)/2);return 0; }?
總結(jié)
以上是生活随笔為你收集整理的扩散(洛谷-P1661)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C++语言基础 —— 数组
- 下一篇: 有理数取余(洛谷-P2613)