动态规划:NOI2013 快餐店
Description
小 T打算在城市C开设一家外送快餐店。送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近 的地方。 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑。任意两个建筑之间至少存在一条由双向道路连接而成的路径。小T的快餐店可以开设在任一建筑 中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数)。 现给定城市C的地图(道路分布及其长度),请找出最佳的快餐店选址,输出其与最远的顾客之间的距离。
Input
第一行包含一个整数N,表示城市C中的建筑和道路数目。
接下来N行,每行3个整数,Ai,Bi,Li(1≤i≤N;Li>0),表示一条道路连接了建筑Ai与Bi,其长度为Li 。
Output
仅包含一个实数,四舍五入保留恰好一位小数,表示最佳快餐店选址距离最远用户的距离。
注意:你的结果必须恰好有一位小数,小数位数不正确不得分。
Sample Input
1 2 1
1 4 2
1 3 2
2 4 1
1 4 2
1 3 2
2 4 1
Sample Output
2.0
HINT
数据范围
对于 10%的数据,N<=80,Li=1;
对于 30%的数据,N<=600,Li<=100;
对于 60% 的数据,N<=2000,Li<=10^9;
对于 100% 的数据,N<=10^5,Li<=10^9
这个DP有点屌……
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 typedef long long LL; 6 const int N=100010; 7 int n,cnt,fir[N],nxt[N<<1],to[N<<1]; 8 LL val[N<<1],dis[N],ans,sum,Mx; 9 LL u1[N],v1[N],b[N],c[N]; 10 LL u2[N],v2[N]; 11 bool ring[N]; 12 void addedge(int a,int b,int v){ 13 nxt[++cnt]=fir[a]; 14 val[cnt]=v; 15 fir[a]=cnt; 16 to[cnt]=b; 17 } 18 19 int ID[N],tot; 20 int st[N],top; 21 int pre[N]; 22 void DFS(int x){ 23 ID[x]=++tot; 24 for(int i=fir[x],y;i;i=nxt[i]) 25 if((y=to[i])!=pre[x]){ 26 if(!ID[y]){ 27 pre[y]=x; 28 c[y]=val[i]; 29 DFS(y); 30 } 31 else if(ID[y]>ID[x]){ 32 while(x!=y){ 33 st[++top]=y; 34 b[top]=c[y]; 35 ring[y]=true; 36 y=pre[y]; 37 } 38 st[++top]=x; 39 b[top]=val[i]; 40 ring[x]=true; 41 return; 42 } 43 } 44 } 45 46 void DP(int x,int fa){ 47 for(int i=fir[x];i;i=nxt[i]) 48 if(to[i]!=fa&&!ring[to[i]]){ 49 DP(to[i],x); 50 ans=max(ans,dis[x]+dis[to[i]]+val[i]); 51 dis[x]=max(dis[x],dis[to[i]]+val[i]); 52 } 53 } 54 55 int main(){ 56 freopen("foodshop.in","r",stdin); 57 freopen("foodshop.out","w",stdout); 58 scanf("%d",&n); 59 for(int i=1,x,y,v;i<=n;i++){ 60 scanf("%d%d%d",&x,&y,&v); 61 addedge(x,y,v);addedge(y,x,v); 62 } 63 DFS(1); 64 for(int i=1;i<=top;i++)DP(st[i],0); 65 66 for(int i=1;i<=top;i++){ 67 sum+=b[i-1]; 68 u1[i]=max(u1[i-1],sum+dis[st[i]]); 69 v1[i]=max(v1[i-1],sum+dis[st[i]]+Mx); 70 Mx=max(Mx,dis[st[i]]-sum); 71 } 72 LL tmp=b[top];Mx=sum=b[top]=0; 73 for(int i=top;i>=1;i--){ 74 sum+=b[i]; 75 u2[i]=max(u2[i+1],sum+dis[st[i]]); 76 v2[i]=max(v2[i+1],sum+dis[st[i]]+Mx); 77 Mx=max(Mx,dis[st[i]]-sum); 78 } 79 LL Mn=v1[top]; 80 for(int i=1;i<top;i++) 81 Mn=min(Mn,max(max(v1[i],v2[i+1]),tmp+u1[i]+u2[i+1])); 82 ans=max(ans,Mn); 83 printf("%.1lf",ans/2.0); 84 return 0; 85 }
尽最大的努力,做最好的自己!