• [POI2018]Plan metra


    题目大意:
      一棵$n(nle5 imes10^5)$个结点的树,每条边的边权均为正整数,告诉你$2sim n-1$号结点到$1$号点和$n$号点的距离$d1[i]$和$d2[i]$。求是否存在这样的树,若存在,则构造出这样一棵树。

    思路:
      若对于所有的$1<i<n$,$|d1[i]-d2[i]|$都相等,则$1$与$n$直接相连,其余点与$1$和$n$中最近的点相连。
      否则若存在这样的树,肯定能构造出一种方案,使得$d1[n]=min{d1[i]+d2[i]}$。令$d=min{d1[i]+d2[i]}$,若点$i$满足$d1[i]+d2[i]=d$,则$i$一定在$1$到$n$的链上。通过排序可以求出$1$到$n$的链,如果发现有两点在同一位置,则构造失败。对于剩下的点$i$,向满足$d1[j]=d-frac{d1[i]-d2[i]+d}2$的点$j$连一条长度为$d1[i]-d1[j]$的边即可,如果不存在这样的点$j$,则构造失败,若新建边长度不为正整数则还是构造失败。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<algorithm>
     4 #include<sys/mman.h>
     5 #include<sys/stat.h>
     6 class MMapInput {
     7     private:
     8         char *buf,*p;
     9         int size;
    10     public:
    11         MMapInput() {
    12             register int fd=fileno(stdin);
    13             struct stat sb;
    14             fstat(fd,&sb);
    15             size=sb.st_size;
    16             buf=reinterpret_cast<char*>(mmap(0,size,PROT_READ,MAP_PRIVATE,fileno(stdin),0));
    17             p=buf;
    18         }
    19         char getchar() {
    20             return (p==buf+size||*p==EOF)?EOF:*p++;
    21         }
    22 };
    23 MMapInput mmi;
    24 inline int getint() {
    25     register char ch;
    26     while(!isdigit(ch=mmi.getchar()));
    27     register int x=ch^'0';
    28     while(isdigit(ch=mmi.getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    29     return x;
    30 }
    31 const int N=5e5+1,C=1e6;
    32 int d1[N],d2[N],cnt,tmp[N],mem[C<<1],*vis=mem+C;
    33 struct Edge {
    34     int u,v,w;
    35 };
    36 Edge e[N];
    37 inline bool cmp(const int &a,const int &b) {
    38     return d1[a]<d1[b];
    39 }
    40 int main() {
    41     const int n=getint();
    42     if(n==2) {
    43         puts("TAK
    1 2 1");
    44         return 0;
    45     }
    46     for(register int i=2;i<n;i++) d1[i]=getint();
    47     for(register int i=2;i<n;i++) d2[i]=getint();
    48     if(d1[2]!=d2[2]) {
    49         for(register int i=3;i<n;i++) {
    50             if(std::abs(d1[i]-d2[i])!=std::abs(d1[2]-d2[2])) goto case2;
    51         }
    52         e[cnt++]=(Edge){1,n,std::abs(d1[2]-d2[2])};
    53         for(register int i=2;i<n;i++) {
    54             e[cnt++]=(Edge){i,d1[i]>d2[i]?n:1,std::min(d1[i],d2[i])};
    55         }
    56     } else case2: {
    57         int d=C*2;
    58         for(register int i=2;i<n;i++) {
    59             d=std::min(d,d1[i]+d2[i]);
    60         }
    61         d1[n]=d2[1]=d;
    62         for(register int i=1;i<=n;i++) {
    63             if(d1[i]+d2[i]==d) {
    64                 vis[d1[i]]=tmp[++tmp[0]]=i;
    65             }
    66         }
    67         std::sort(&tmp[1],&tmp[tmp[0]]+1,cmp);
    68         for(register int i=2;i<=tmp[0];i++) {
    69             if(d1[tmp[i]]==d1[tmp[i-1]]) {
    70                 puts("NIE");
    71                 return 0;
    72             }
    73             e[cnt++]=(Edge){tmp[i-1],tmp[i],d1[tmp[i]]-d1[tmp[i-1]]};
    74         }
    75         for(register int i=1;i<=n;i++) {
    76             if(d1[i]+d2[i]==d) continue;
    77             const int j=vis[(d1[i]-d2[i]+d)/2];
    78             if((d1[i]+d2[i]-d)%2||!j) {
    79                 puts("NIE");
    80                 return 0;
    81             }
    82             e[cnt++]=(Edge){j,i,d1[i]-d1[j]};
    83         }
    84     }
    85     puts("TAK");
    86     for(register int i=0;i<cnt;i++) {
    87         printf("%d %d %d
    ",e[i].u,e[i].v,e[i].w);
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    利用windows 127.0.0.1:30000 代理在linux下工作
    nginx与ssh 把内网转为公网开发服务器
    php errorlog 记录
    dockerfile php 开发
    ubuntu
    k8s 1.9.1 centos7 install 离线安装
    kubernetes
    linux字符设备驱动--基本知识介绍
    linux应用程序设计--Makefile工程管理
    linux应用程序设计--GDB调试
  • 原文地址:https://www.cnblogs.com/skylee03/p/8722152.html
Copyright © 2020-2023  润新知