jzoj1405 电缆建设

来源:互联网 发布:我就是社工库最新域名 编辑:程序博客网 时间:2024/04/27 16:59

Problem

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

分析

特殊的平面图求MST。当然是要寻找性质。
这里写图片描述
第一点,树边不可能相交。相交后,必然存在更优方案使得原生成树成立。
第二点,若存在图2情况,则AC不可能是树边。证明如下:
反证法,假设AC是树边。
由钝角三角形可得,AB< AC,BC< AC,
由于AC是树边,所以不存在边交叉与AC。
1. 若AB< BC,
因为AC是树边,所以做到AC时A、C不连通。所以AB、BC不会同时选。因为无法交叉,边权又从小到大做,所以AB要么直接连通,要么中间点为AB上的点。也就等价于选AB这条边。那么既然选AB,AC,那么为什么不选完全等价的AB,BC使得答案更优秀呢?
2. 若AB>BC,基本同理。

CODE

#include <cstdio>#include <iostream>#include <algorithm>#include <cmath>#define maxn 600100#define sqr(x) ((x)*(x))#define dis(a,b) (sqrt(sqr(x1-x2)+sqr(yy1[a]-y2[b])))typedef double db;typedef int ll;using namespace std;ll tot;ll n,m,x1,x2;long long yy1[maxn],y2[maxn],fa[maxn*2];struct Edge{    ll a,b;    db w;    Edge() {a=b=w=0;}    Edge(ll _a,ll _b,db _w) {a=_a,b=_b,w=_w;}} es[maxn*4];ll read(ll &n) {    char ch=' ';ll 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;}ll gf(ll x) {    if (fa[x]==0) return x;    return fa[x]=gf(fa[x]);}bool cmp(Edge a,Edge b) {return a.w<b.w;}int main() {    cin>>n>>m>>x1>>x2;    ll a=0;    for (ll i=1; i<=n; i++) {        read(a),yy1[i]=yy1[i-1]+a;    }    for (ll i=1; i<=m; i++) {        read(a),y2[i]=y2[i-1]+a;    }    for (ll i=1; i<n; i++) es[++tot]=Edge(i,i+1,yy1[i+1]-yy1[i]);    for (ll i=1; i<m; i++) es[++tot]=Edge(i+n,n+i+1,y2[i+1]-y2[i]);    ll j=0;    for (ll i=1; i<=n; i++) {        while (j<m && y2[j+1]<=yy1[i]) j++;        if (i==2 && j==11) {            int kkk=i;        }        if (j!=0) es[++tot]=Edge(i,j+n,dis(i,j));    }    j=m+1;    for (ll i=n; i; i--) {        while (j>1 && y2[j-1]>=yy1[i]) j--;        if (i==2 && j==11) {            int kkk=i;        }        if (j!=m+1) es[++tot]=Edge(i,j+n,dis(i,j));    }    sort(es+1,es+1+tot,cmp);    ll cnt=0;    db ans=0;    int f1,f2;    for (ll i=1; i<=tot; i++) {        f1=gf(es[i].a); f2=gf(es[i].b);        if (f1!=f2) {            fa[f1]=f2;            ans+=es[i].w; cnt++;            if (cnt==n+m-1) break;        }    }    printf("%.2lf",ans);}
0 0
原创粉丝点击