【JZOJ 1405】电缆建设

来源:互联网 发布:青藏铁路公司官网通知 编辑:程序博客网 时间:2024/04/27 14:03

Description

  教主上电视了,但是蔚蓝城郊区沿河的村庄却因电缆线路老化而在直播的时候停电,这让市长SP先生相当的愤怒,他决定重修所有电缆,并改日播放录像,杜绝此类情况再次发生。
  河流两旁各有n,m个村庄,每个村庄可以用二维坐标表示,其中河流一旁的村庄横坐标均为x1,河流另一旁的村庄横坐标均为x2。由于地势十分开阔,任意两个村庄可以沿坐标系直线修建一条电缆连接,长度即为两村庄的距离。要修建若干条电缆,使得任意两个村庄都可以通过若干个有电缆连接的村庄相连。
  因为修建的经费与长度成正比,SP市长当然希望所花的钱越少越好,所以他希望你来帮助他设计一套方案,使得电缆总长度最小,并告诉所需要的电缆总长度。

Solution

这题贪心的想一下,即可优化成4nlogn的DP;

当然,用DP优化一下,即可变成O(nlogn)的,先打混排序,
设两个f,g一个表示下面联通了,一个表示还未联通,互相转移;

复杂度:O(nlog(n))

Code

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cmath>#define fo(i,a,b) for(int i=a;i<=b;i++)#define sqr(q) ((q)*(q))using namespace std;typedef double db;typedef long long LL;const int N=600100;int read(int &n){    char ch=' ';int q=0,w=1;    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());    if(ch=='-')w=-1,ch=getchar();    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}int n,n1;LL y[N],yy[N],b0,x1,x2;struct qqww{    db v;int x,y;}b[N*4];int g[N*2];db ans;bool PX(qqww q,qqww w){return q.v<w.v;}int gf(int q){return g[q]=(g[q]==q?q:gf(g[q]));}int main(){    int q;    read(n),read(n1),x1=read(q),x2=read(q);    fo(i,1,n)y[i]=y[i-1]+read(q);    fo(i,1,n1)yy[i]=yy[i-1]+read(q);    fo(i,2,n)b[++b0].v=abs(y[i]-y[i-1]),b[b0].x=i,b[b0].y=i-1;    fo(i,2,n1)b[++b0].v=abs(yy[i]-yy[i-1]),b[b0].x=i+n,b[b0].y=i+n-1;    q=1;    fo(i,1,n)if(y[i]>=yy[q])    {        while(q<n1&&yy[q+1]<=y[i])q++;        b[++b0].v=sqrt(sqr(x2-x1)+sqr(yy[q]-y[i])),b[b0].x=i,b[b0].y=q+n;    }    q=1;    fo(i,1,n1)if(y[q]<=yy[i])    {        while(q<n&&y[q+1]<=yy[i])q++;        b[++b0].v=sqrt(sqr(x2-x1)+sqr(yy[i]-y[q])),b[b0].x=i+n,b[b0].y=q;    }    sort(b+1,b+1+b0,PX);    fo(i,1,n+n1)g[i]=i;    q=0;    fo(i,1,b0)    {        if(q==n+n1-1)break;        int x=gf(b[i].x),y=gf(b[i].y);        if(x!=y)        {            q++;            ans+=b[i].v;            g[x]=y;        }    }    printf("%.2lf\n",ans);    return 0;}
0 0
原创粉丝点击