[BZOJ5100][POI2018]Plan metra(构造)

若1与n直接相连,则所有点到1与n的距离差的绝对值是相同的,根据距离选择与1还是n直接相连即可。

若不直接相连,则其余所有点到1与n的距离和的最小值就是1到n的距离。

找到所有在1到n的路径上的点,按与1的距离排序,然后相邻的两两连边。其余点算出应该挂在链上哪个点下面,注意判断各种不合法即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 typedef long long ll;
 5 using namespace std;
 6 
 7 const int N=1000010;
 8 int n,a[N],b[N],id[N];
 9 struct P{ int x,i; }d[N];
10 bool operator <(const P &a,const P &b){ return a.x<b.x; }
11 
12 int main(){
13     freopen("bzoj5100.in","r",stdin);
14     freopen("bzoj5100.out","w",stdout);
15     scanf("%d",&n);
16     rep(i,2,n-1) scanf("%d",&a[i]);
17     rep(i,2,n-1) scanf("%d",&b[i]);
18     if (n==2){ printf("TAK\n1 2 1\n"); return 0; }
19     int len=abs(a[2]-b[2]);
20     rep(i,3,n-1) if (abs(a[i]-b[i])!=len){ len=0; break; }
21     if (len){
22         puts("TAK"); printf("1 %d %d\n",n,len);
23         rep(i,2,n-1)
24             if (a[i]>b[i]) printf("%d %d %d\n",i,n,b[i]);
25                 else printf("%d %d %d\n",i,1,a[i]);
26         return 0;
27     }
28     len=2000000; int tot=0;
29     rep(i,2,n-1) len=min(len,a[i]+b[i]);
30     rep(i,2,n) if (a[i]+b[i]==len) d[++tot]=(P){a[i],i};
31     sort(d+1,d+tot+1); d[0]=(P){0,1}; d[++tot]=(P){len,n};
32     rep(i,1,tot) if (d[i].x==d[i-1].x){ puts("NIE"); return 0; }
33     rep(i,0,tot) id[d[i].x]=d[i].i;
34     rep(i,2,n-1) if (a[i]+b[i]>len && (((a[i]+b[i]-len)&1) || !id[a[i]-(a[i]+b[i]-len)/2])){ puts("NIE"); return 0; }
35     puts("TAK");
36     rep(i,1,tot) printf("%d %d %d\n",d[i-1].i,d[i].i,d[i].x-d[i-1].x);
37     rep(i,2,n-1) if (a[i]+b[i]>len) printf("%d %d %d\n",id[a[i]-(a[i]+b[i]-len)/2],i,(a[i]+b[i]-len)/2);
38     return 0;
39 }

猜你喜欢

转载自www.cnblogs.com/HocRiser/p/10259333.html