【BZOJ3242】【UOJ#126】【NOI2013】快餐店
NOI都是這種難度的題怎么玩嘛QAQ
原題:
小T打算在城市C開設一家外送快餐店。送餐到某一個地點的時間與外賣店到該地點之間最短路徑長度是成正比的,小T希望快餐店的地址選在離最遠的顧客距離最近的地方。 快餐店的顧客分布在城市C的N 個建筑中,這N 個建筑通過恰好N 條雙向道路連接起來,不存在任何兩條道路連接了相同的兩個建筑。任意兩個建筑之間至少存在一條由雙向道路連接而成的路徑。小T的快餐店可以開設在任一建筑中,也可以開設在任意一條道路的某個位置上(該位置與道路兩端的建筑的距離不一定是整數)。 現給定城市C的地圖(道路分布及其長度),請找出最佳的快餐店選址,輸出其與最遠的顧客之間的距離。?
N<=10^5,Li<=10^9
?
恩題解比較好理解但是比較難想到……
首先答案不一定是圖上的半徑,比如醬:
因為有環,所以圖上直徑的中點到其它所有點距離的最大值可能比半徑還要大,這個時候半徑就不是最優值
然后顯然答案是環上刪去某邊后樹的直徑,這個寫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?
轉載于:https://www.cnblogs.com/JSL2018/p/6895415.html
總結
以上是生活随笔為你收集整理的【BZOJ3242】【UOJ#126】【NOI2013】快餐店的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS 分类添加属性
- 下一篇: css3完成多边形