1. 程式人生 > >【BZOJ3242】【UOJ#126】【NOI2013】快餐店

【BZOJ3242】【UOJ#126】【NOI2013】快餐店

及其 iostream 記錄 連接 時間 max efi 分布 外賣

NOI都是這種難度的題怎麽玩嘛QAQ

原題:

小T打算在城市C開設一家外送快餐店。送餐到某一個地點的時間與外賣店到該地點之間最短路徑長度是成正比的,小T希望快餐店的地址選在離最遠的顧客距離最近的地方。 快餐店的顧客分布在城市C的N 個建築中,這N 個建築通過恰好N 條雙向道路連接起來,不存在任何兩條道路連接了相同的兩個建築。任意兩個建築之間至少存在一條由雙向道路連接而成的路徑。小T的快餐店可以開設在任一建築中,也可以開設在任意一條道路的某個位置上(該位置與道路兩端的建築的距離不一定是整數)。 現給定城市C的地圖(道路分布及其長度),請找出最佳的快餐店選址,輸出其與最遠的顧客之間的距離。

N<=10^5,Li<=10^9

恩題解比較好理解但是比較難想到……

首先不知道為什麽答案不是圖地直徑/2……

然後顯然答案是環上刪去某邊後樹的直徑,這個寫n^2算法的時候會用到

然後dfs找出環,對環上每個點令其為根求出高度及直徑

然後順著掃一遍,每次記錄前面所有環上邊的和sum,當前節點子樹高度和sum的和的最大值f1,(前面深度最大和次大子樹的深度的和)和這兩個子樹根節點之間的距離的和的最大值f2

然後反過來再搞一遍搞出f3和f4

統計答案即可,註意還有跨過環上第一個點和最後一個點之間的邊的情況,這個結合f1和f3就行

最後還要用環上所有點的子樹直徑的最大值更新ans(不知道為什麽QAQ

NOI都是這種難度的題怎麽玩嘛QAQ

代碼:

技術分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long
 8 int rd(){int z=0,mk=1;  char ch=getchar();
 9     while(ch<0||ch>9){if(ch==-)mk=-1;  ch=getchar();}
10 while(ch>=0&&ch<=9){z=(z<<3)+(z<<1)+ch-0; ch=getchar();} 11 return z*mk;} 12 struct edg{int nxt,y,v;}e[210000]; int lk[110000],ltp=0; 13 inline void ist(int x,int y,int z){ e[++ltp]=(edg){lk[x],y,z}; lk[x]=ltp;} 14 int n; 15 bool vstd[110000]; int stck[110000],tp=0,fthv[110000]; 16 int ccd[110000],cct=0,ccv[110000]; 17 ll dp[110000]; 18 ll f[110000],f1[110000],f2[110000],f3[110000],f4[110000]; 19 ll mxf=0; 20 bool gtcc(int x,int y){ 21 stck[++tp]=x; 22 if(vstd[x]){ 23 fill(vstd,vstd+1+n,false); 24 do vstd[ccd[++cct]=stck[tp]]=true,ccv[cct]=fthv[stck[tp--]];while(stck[tp]!=x); 25 return true;} 26 vstd[x]=true; 27 for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=y){ 28 fthv[e[i].y]=e[i].v; 29 if(gtcc(e[i].y,x)) return true;} 30 --tp; 31 return false;} 32 void gtdp(int x,int y){ 33 for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=y && !vstd[e[i].y]){ 34 dp[e[i].y]=dp[x]+e[i].v,gtdp(e[i].y,x); 35 mxf=max(mxf,f[x]+f[e[i].y]+e[i].v); 36 f[x]=max(f[x],f[e[i].y]+e[i].v);}} 37 int main(){//freopen("ddd.in","r",stdin); 38 int l,r,z; cin>>n; 39 for(int i=1;i<=n;++i) l=rd(),r=rd(),z=rd(),ist(l,r,z),ist(r,l,z); 40 if(!gtcc(1,0)) return 0; 41 for(int i=1;i<=cct;++i) gtdp(ccd[i],0); 42 ll bwl=0,mx=0,ans=0,tt=ccv[cct],tmp; ccv[cct]=0; 43 for(int i=1;i<=cct;++i){ 44 bwl+=ccv[i-1]; 45 f1[i]=max(f1[i-1],bwl+f[ccd[i]]); 46 f2[i]=max(f2[i-1],mx+bwl+f[ccd[i]]); 47 mx=max(mx,f[ccd[i]]-bwl);} 48 bwl=mx=0; 49 for(int i=cct;i>=1;--i){ 50 bwl+=ccv[i]; 51 f3[i]=max(f3[i+1],bwl+f[ccd[i]]); 52 f4[i]=max(f4[i+1],mx+bwl+f[ccd[i]]); 53 mx=max(mx,f[ccd[i]]-bwl);} 54 ans=f2[cct]; 55 for(int i=1;i<cct;++i){ 56 tmp=max(f1[i]+f3[i+1]+tt,max(f2[i],f4[i+1])); 57 ans=min(ans,tmp);} 58 ans=max(ans,mxf); 59 printf("%.1lf\n",ans*1.0/2); 60 return 0;}
View Code

【BZOJ3242】【UOJ#126】【NOI2013】快餐店