【POJ - 2349】【UVA - 10369】 Arctic Network(最小生成树求权值第k大的边)(内附两种算法)
題干:
The Department of National Defence (DND) wishes to connect several northern outposts by a wireless network. Two different communication technologies are to be used in establishing the network: every outpost will have a radio transceiver and some outposts will in addition have a satellite channel.?
Any two outposts with a satellite channel can communicate via the satellite, regardless of their location. Otherwise, two outposts can communicate by radio only if the distance between them does not exceed D, which depends of the power of the transceivers. Higher power yields higher D but costs more. Due to purchasing and maintenance considerations, the transceivers at the outposts must be identical; that is, the value of D is the same for every pair of outposts.?
Your job is to determine the minimum D required for the transceivers. There must be at least one communication path (direct or indirect) between every pair of outposts.
Input
The first line of input contains N, the number of test cases. The first line of each test case contains 1 <= S <= 100, the number of satellite channels, and S < P <= 500, the number of outposts. P lines follow, giving the (x,y) coordinates of each outpost in km (coordinates are integers between 0 and 10,000).
Output
For each case, output should consist of a single line giving the minimum D required to connect the network. Output should be specified to 2 decimal points.
Sample Input
1 2 4 0 100 0 300 0 600 150 750Sample Output
212.13題目大意:
南極有n個科研站, 要把這些站用衛星或者無線電連接起來,使得任意兩個都能直接或者間接相連。任意兩個都有安裝衛星設備的,都可以直接通過衛星通信,不管它們距離有多遠。 而安裝有無線電設備的兩個站,距離不能超過D。 D越長費用越多。
現在有s個衛星設備可以安裝,還有足夠多的無線電設備,求一個方案,使得費用D最少(D取決與所有用無線電通信的花費最大的那條路徑)。
題意:有n個點給出坐標,點和點之間可以用無線電或者衛星通信,每個點都有無線電收發器可進行無線電通信,但是只有m個點有衛星通信功能。衛星通信的距離可以無限大,但無線電通信的距離不能超過D,超過D的部分將使通信費用增加。要使通信費用最少。
其實就是求一次最小生成樹,m個點有衛星通信,那么就會有m-1條邊的通信距離無限大,其實就是這m-1條邊不用計算費用。而剩下的邊中,找出最大邊作為D值,這樣剩下的所有的邊都不會大于D,那么不會增加通信費用。在構建MST過程中保存下所有的邊權值,然后按升序排序,除掉最后的m-1條邊(也就是最大的m-1條邊,這些邊用衛星通信),最大的那條就是D;
解題報告:
? ? ?注意題目中 ?有s個衛星,也就是說可以連s-1條邊!所以最后答案還要+1
ac代碼:(329ms ?2.2MB)(用m==n-1跳出循環也才313ms)(用double然后算dist的時候就用sqrt也不算慢,,344ms)
#include<iostream> #include<cmath> #include<cstdio> #include<algorithm> const int MAX = 500 + 5;using namespace std; int s,p; int top; long long ans[1000]; int f[MAX]; struct Node {int x,y; } node[MAX]; struct Edge {int u,v;//別寫x,y、其實更準確說應該是u和v,因為這時候你存的是兩個點。你如果用x和y代表一個點的話,那就需要用x1x2y1y2來表示Edge結構體了 long long w;//權值 在此處就是距離 // Edge(int u,int v,long long w) : u(u),v(v),w(w) {} }edge[MAX * MAX + 5]; bool cmp(const Edge & a,const Edge & b) {return a.w<b.w;} int getf(int v) {return f[v] == v ? v : f[v] = getf(f[v] ); } void merge(int u, int v) {int t1 = getf(u );int t2 = getf(v );if(t1 != t2) {f[t2] =t1;} } int main() {int t;cin>>t;long long dist;while(t--) {//留給初始化 top = 0;for(int i = 0; i<MAX; i++) {f[i]=i;}scanf("%d %d",&s,&p);//有 p 個點, 即p就是以前的n for(int i= 0; i<p;i++) {//從0開始讀的! scanf("%d %d",&node[i].x,&node[i].y); }for(int i = 0; i<p; i++) {for(int j = i+1; j<p; j++) {top++;dist = (node[i].x-node[j].x )*(node[i].x-node[j].x ) + (node[i].y-node[j].y )*(node[i].y-node[j].y );//edge[top] = (i,j,dist); // printf("****%lld\n",dist);edge[top].u=i;edge[top].v=j;edge[top].w=dist; }}int cur=0;sort(edge + 1,edge+top +1,cmp);for(int i = 1; i<=top; i++) {if(getf(edge[i].u) != getf(edge[i].v ) ) {merge(edge[i].u ,edge[i].v );++cur;ans[cur] = edge[i].w;}} // printf("cur = %d\n",cur); // for(int i = 1; i<=cur; i++) { // printf("%lld ",ans[i]); // }printf("%.2f\n",sqrt(ans[cur-(s - 1) ] * 1.0) );}return 0 ;}AC代碼2:(prim算法)(32ms,2.1MB)
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define N 505 using namespace std; double x[N], y[N], w[N][N], key[N], ans[N*N]; int n,m,pre[N],hash[N]; inline double getDist(double x1,double y1,double x2,double y2){return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); }double Prim(){memset(hash, 0, sizeof(hash));hash[1] = 1;for(int i=1; i<=n; ++i){key[i] = w[1][i]; pre[i] = 1;}int k=0;for(int i=1; i<n; ++i){int u=-1;for(int j=1; j<=n; ++j)if(!hash[j]){if(u==-1 || key[j]<key[u]) u=j;}ans[k++] = key[u];hash[u] = 1;for(int j=1; j<=n; ++j)if(!hash[j]&&key[j]>w[u][j]){key[j]=w[u][j]; pre[j]=u;}}sort(ans, ans+k);return ans[k-m]; }int main(){int T;scanf("%d",&T);while(T--){scanf("%d%d",&m,&n);for(int i=1; i<=n; ++i)scanf("%lf%lf",&x[i],&y[i]);int pos=0;memset(w, 0, sizeof(w));for(int i=1; i<=n; ++i){for(int j=i+1; j<=n; ++j){w[i][j]=w[j][i]=getDist(x[i],y[i],x[j],y[j]);}} printf("%.2f\n", Prim());}return 0; }?
總結:
? ?注意該用top的地方用top,該ij的地方ij,該uv的地方uv!!for(int i = 1; i<=top; i++) { ? a[top] = ...? }這種錯別再犯啦!是n的時候還好,就怕這種i<top啊 i<u啊i<v ?里面getf(i)就順手寫成getf(v)了。
?
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【POJ - 2349】【UVA - 10369】 Arctic Network(最小生成树求权值第k大的边)(内附两种算法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: scanexplicit.exe - s
- 下一篇: ScanMailOutLook.exe