日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Ink on paper 最小生成树-Prim-二分答案并查集

發布時間:2025/3/19 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Ink on paper 最小生成树-Prim-二分答案并查集 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意 :

  • 平面直角坐標系中有n個水滴,每個水滴以0.5cm的速度擴散,求經過多久所有的水滴可以連接在一起。

思路 :

  • 將任意兩個墨水滴連接并求解最小生成樹就是墨水恰好全部連接時的情況。全部連接的時間就是最小生成樹中最長的邊形成的時間。求時間的平方,且 t2=s2t^2 = s^2t2=s2, 因此不用對距離開根號。O(n2n^2n2),1s,2 <= n <= 5000,n2=2.5e7n^2 = 2.5e7n2=2.5e7。
#include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <vector> #include <unordered_map> #include <unordered_set> #include <set> #include <map> #define endl '\n' #define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) using namespace std; const double pi = acos(-1); typedef long long ll;const int N = 5010, inf = 0x3f3f3f3f; ll g[N][N]; ll dist[N]; bool st[N]; int n;pair<ll, ll> a[N];ll getd(int x, int y) {return (a[x].first - a[y].first) * (a[x].first - a[y].first) + (a[x].second - a[y].second) * (a[x].second - a[y].second); }ll prim() {// prim算法初始化memset(dist, 0x3f, sizeof dist);memset(st, 0, sizeof st);ll mx = 0; // 最小生成樹中的最長邊for (int i = 0; i < n; i ++ ){int t = -1;for (int j = 1; j <= n; j ++ )if (!st[j] && (t == -1 || dist[j] < dist[t]))t = j;st[t] = true;if (i)mx = max(mx, dist[t]);for (int j = 1; j <= n; j ++ )dist[j] = min(dist[j], g[t][j]);}return mx; }int main() { // IOS;int T;scanf("%d", &T);while (T -- ){// 初始化圖memset(g, 0x3f, sizeof g);scanf("%d", &n);for (int i = 1; i <= n; i ++ ) scanf("%lld%lld", &a[i].first, &a[i].second);// 建圖for (int i = 1; i <= n; i ++ )for (int j = i + 1; j <= n; j ++ )g[i][j] = g[j][i] = getd(i, j);printf("%lld\n", prim());}return 0; }

以下貼上二分答案并查集的ac代碼(來自隊友)

#include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 5050;int fa[maxn+10]; void init(int n){for(int i = 1; i <= n; i++)fa[i]=i;} int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} void merge(int x, int y){x=find(x);y=find(y);if(x!=y)fa[x]=y;} int count(int n){int cnt=0; for(int i = 1; i <= n; i++)if(fa[i]==i)cnt++;return cnt;}int n; struct node{LL x, y; }a[maxn]; LL d[maxn][maxn]; bool cmp(node x, node y){return x.x!=y.x ?x.x<y.x :x.y<y.y;} LL getd(node x, node y){return (x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y);} bool check(LL t){init(n);int cnt = 1;for(int i = 1; i <= n; i++){for(int j = i+1; j <= n; j++){if(t>=d[i][j]){if(find(i)!=find(j)){cnt++;if(cnt==n)break;merge(i,j);}}}if(cnt==n)break;}return cnt==n; }int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int T; cin>>T;while(T--){cin>>n; for(int i = 1; i <= n; i++)cin>>a[i].x>>a[i].y;for(int i = 1; i <= n; i++)for(int j = i+1; j <= n; j++)d[i][j] = getd(a[i],a[j]);//sort(a+1,a+n+1,cmp);LL l = 0, r = 1e15+10;while(l < r){LL mid = (l+r)/2;if(check(mid)){r = mid;}else {l = mid+1;}}cout<<r<<"\n";}return 0; }

總結

以上是生活随笔為你收集整理的Ink on paper 最小生成树-Prim-二分答案并查集的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。