[NOI2013]快餐店
題目描述
小T打算在城市C開設一家外送快餐店。送餐到某一個地點的時間與外賣店到該地點之間最短路徑長度是成正比的,小T希望快餐店的地址選在離最遠的顧客距離最近的地方。
快餐店的顧客分布在城市C的N 個建筑中,這N 個建筑通過恰好N 條雙向道路連接起來,不存在任何兩條道路連接了相同的兩個建筑。任意兩個建筑之間至少存在一條由雙向道路連接而成的路徑。小T的快餐店可以開設在任一建筑中,也可以開設在任意一條道路的某個位置上(該位置與道路兩端的建筑的距離不一定是整數)。
現給定城市C的地圖(道路分布及其長度),請找出最佳的快餐店選址,輸出其與最遠的顧客之間的距離。
輸入輸出格式
輸入格式:
?
輸入文件foodshop.in第一行包含一個整數N,表示城市C中的建筑和道路數目。
接下來N行,每行3個整數,Ai,Bi,Li(1≤i≤N;Li>0),表示一條道路連接了建筑Ai與Bi,其長度為Li 。
?
輸出格式:
?
輸出文件foodshop.out僅包含一個實數,四舍五入保留恰好一位小數,表示最佳快餐店選址距離最遠用戶的距離。
注意:你的結果必須恰好有一位小數,小數位數不正確不得分。
?
輸入輸出樣例
輸入樣例#1:【樣例輸入1】 4 1 2 1 1 4 2 1 3 2 2 4 1 【樣例輸入2】 5 1 5 100 2 1 77 3 2 80 4 1 64 5 3 41 輸出樣例#1:
【樣例輸出1】 2.0 【樣例輸出2】 109.0
說明
樣例1
樣例2
數據范圍
對于 10%的數據,N<=80,Li=1;
對于 30%的數據,N<=600,Li<=100;
對于 60% 的數據,N<=2000,Li<=10^9;
對于 100% 的數據,N<=10^5,Li<=10^9
顯然這是一棵基環樹. 那么先考慮樹上的做法,答案就是直徑/2. 現在有一個環了,那么最長鏈就有可能經過環上的點. 把環上的每條邊去掉之后跑直徑,然后取一個最小值就是答案了. 這樣的復雜度是n^2的,但只TLE了4個點?但還有WA的,不知道是寫錯了還是什么原因. 最長鏈要么在某一棵子樹里,要么由某兩顆子樹的最長鏈和環上的一段組成. 那么就先預處理出每棵子樹中的最長鏈,記為dis. 然后把環上的點記一個起點,記一個前綴和. 那么就設pre[i]為i之前的點組成的最長鏈的長度,suf類似. 最后枚舉每一條邊,分三種情況取最大值就是斷這一條邊的答案. 復雜度O(n).1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<algorithm> 7 #include<map> 8 #include<complex> 9 #include<queue> 10 #include<stack> 11 #include<cmath> 12 #include<set> 13 #include<vector> 14 #define maxn 100010 15 #define mk make_pair 16 #define LL long long 17 #define inf 1e17 18 using namespace std; 19 struct data{ 20 int nex,to,w; 21 }e[maxn*2]; 22 int head[maxn],edge=-1,dad[maxn],n; 23 LL dis[maxn],pre[maxn],suf[maxn],p1[2][maxn],p2[2][maxn],sum[2][maxn],ans=0; 24 bool flag=0,bj[maxn],huan[maxn]; 25 vector<int>clc,eg; 26 map<pair<int,int>,int>mp; 27 queue<int>q; 28 inline void add(int from,int to,int w){ 29 e[++edge].nex=head[from]; 30 e[edge].to=to; 31 e[edge].w=w; 32 head[from]=edge; 33 } 34 inline void out(int x){ 35 if(flag) return; 36 int xx=x;x=dad[x]; 37 while(x!=xx) clc.push_back(x),x=dad[x]; 38 clc.push_back(xx); 39 } 40 void dfs(int x,int fa){ 41 if(flag) return; 42 for(int i=head[x];i!=-1;i=e[i].nex){ 43 int v=e[i].to; 44 if(v==fa) continue; 45 if(dad[v]) {dad[v]=x;out(v);flag=1;return;} 46 dad[v]=x;dfs(v,x); 47 } 48 } 49 void dp(int x,int fa){ 50 for(int i=head[x];i;i=e[i].nex){ 51 int v=e[i].to; 52 if(v==fa || huan[v]) continue; 53 dp(v,x); 54 ans=max(ans,dis[x]+dis[v]+e[i].w); 55 dis[x]=max(dis[v]+e[i].w,dis[x]); 56 } 57 } 58 int main(){ 59 memset(head,-1,sizeof(head)); 60 int x,y,z; 61 scanf("%d",&n); 62 for(int i=1;i<=n;i++) 63 scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z),mp[mk(x,y)]=edge,mp[mk(y,x)]=edge; 64 dad[1]=1,dfs(1,0); 65 for(int i=0;i<clc.size();i++) huan[clc[i]]=1; 66 for(int i=0;i<clc.size();i++) dp(clc[i],0); 67 int len=clc.size(); 68 p1[0][0]=p2[0][0]=dis[clc[0]];pre[0]=-inf; 69 for(int i=1;i<len;i++){ 70 int u=clc[i-1],v=clc[i]; 71 sum[0][i]=sum[0][i-1]+e[mp[mk(u,v)]].w; 72 p1[0][i]=max(p1[0][i-1],dis[v]+sum[0][i]); 73 p2[0][i]=max(p2[0][i-1],dis[v]-sum[0][i]); 74 pre[i]=max(pre[i-1],dis[v]+sum[0][i]+p2[0][i-1]); 75 } 76 clc.push_back(clc[0]); 77 p1[1][len]=p2[1][len]=dis[clc[len]];suf[len]=-inf; 78 for(int i=len-1;i>0;i--){ 79 int u=clc[i+1],v=clc[i]; 80 sum[1][i]=sum[1][i+1]+e[mp[mk(u,v)]].w; 81 p1[1][i]=max(p1[1][i+1],dis[v]+sum[1][i]); 82 p2[1][i]=max(p2[1][i+1],dis[v]-sum[1][i]); 83 suf[i]=max(suf[i+1],dis[v]+sum[1][i]+p2[1][i+1]); 84 } 85 LL g=inf; 86 for(int i=1;i<len;i++){ 87 LL now=p1[0][i-1]+p1[1][i]; 88 now=max(now,max(pre[i-1],suf[i])); 89 g=min(g,now); 90 } 91 printf("%.1lf",(double)max(g,ans)/2); 92 return 0; 93 }
?
轉載于:https://www.cnblogs.com/pantakill/p/7502737.html
總結
以上是生活随笔為你收集整理的[NOI2013]快餐店的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UVa 129 - Krypto
- 下一篇: 同步设备IO与异步设备IO