【BZOJ 3242】 (环套树、线段树+树形DP?)
3242: [Noi2013]快餐店
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 728 Solved: 390Description
小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 1Sample Output
2.0HINT
数据范围
对于 10%的数据,N<=80,Li=1;
对于 30%的数据,N<=600,Li<=100;
对于 60% 的数据,N<=2000,Li<=10^9;
对于 100% 的数据,N<=10^5,Li<=10^9Source
【分析】
这题好难啊。。
首先是,显然求的是树上的最长链。但是这是一个环套树。
对于基环树上的点,求出他们两两间的最长链,这个用树形DP,其实dfs一遍就好了。
当然也是可以走环的,如果走环的话,环可以走两边,肯定选了最近的一边走了。这个最长链一定是断掉环的某边之后那棵树的最长链。
所以可以枚举断掉环上某条边。问现在的最长链,取最优那个即可。
这个怎么做呢?
求出f[i]表示i是环上一点,他的基环树向下的最长链是f[i]。
假设断掉了某条边,环变成了链,那么记录一个sm[i]表示到左端点的距离
对于环上两点i,j,则最长链有sm[j]-sm[i]+f[i]+f[j]=(f[i]-sum[i])+(sm[j]+f[j])
就是维护两个东西,f[i]-sum[i]和f[i]+sm[i],选两个最大的加起来。
但是这两个最大的不能是同一个id,所以还要维护次大值。
当你枚举另一条断边的时候,只要修改一个sm值就好了。
【一开始LL没开,INF太小哭。。【然后一生气又全开LL了ORZ
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 100010 8 // #define INF 0x7fffffff 9 #define LL long long 10 const LL INF=1LL<<60; 11 12 LL mymax(LL x,LL y) {return x>y?x:y;} 13 LL mymin(LL x,LL y) {return x<y?x:y;} 14 15 LL n,r1[Maxn],r2[Maxn],rr[Maxn],nc[Maxn]; 16 LL cc[Maxn]; 17 18 struct node 19 { 20 LL x,y,c,next; 21 }t[Maxn*2]; 22 LL first[Maxn],len; 23 LL fa[Maxn]; 24 25 LL ffa(LL x) 26 { 27 if(fa[x]!=x) fa[x]=ffa(fa[x]); 28 return fa[x]; 29 } 30 31 void ins(LL x,LL y,LL c) 32 { 33 t[++len].x=x;t[len].y=y;t[len].c=c; 34 t[len].next=first[x];first[x]=len; 35 } 36 37 LL cr[Maxn]; 38 39 bool dfs(LL x,LL ff,LL nw) 40 { 41 if(x==r2[nw]) {cr[++cr[0]]=x;cc[cr[0]]=nc[nw];return 1;} 42 for(LL i=first[x];i;i=t[i].next) if(t[i].y!=ff) 43 { 44 if(dfs(t[i].y,x,nw)) {cr[++cr[0]]=x;cc[cr[0]]=t[i].c;return 1;} 45 } 46 return 0; 47 } 48 49 bool vis[Maxn]; 50 LL ln[Maxn]; 51 52 struct nnode 53 { 54 LL l,r,lc,rc; 55 LL mx1,mx2,m1,m2,id1,id2; 56 }tr[Maxn*2]; 57 58 void upd(LL x) 59 { 60 LL lc=tr[x].lc,rc=tr[x].rc; 61 tr[x].mx1=mymax(tr[lc].mx1,tr[rc].mx1); 62 tr[x].id1=tr[lc].mx1>tr[rc].mx1?tr[lc].id1:tr[rc].id1; 63 tr[x].mx2=tr[lc].mx1>tr[rc].mx1?mymax(tr[lc].mx2,tr[rc].mx1):mymax(tr[lc].mx1,tr[rc].mx2); 64 65 tr[x].m1=mymax(tr[lc].m1,tr[rc].m1); 66 tr[x].id2=tr[lc].m1>tr[rc].m1?tr[lc].id2:tr[rc].id2; 67 tr[x].m2=tr[lc].m1>tr[rc].m1?mymax(tr[lc].m2,tr[rc].m1):mymax(tr[lc].m1,tr[rc].m2); 68 } 69 70 LL tot=0,sm[Maxn]; 71 LL build(LL l,LL r,LL nw) 72 { 73 LL x=++tot; 74 tr[x].l=l;tr[x].r=r; 75 if(l==r) 76 { 77 LL id=l+rr[nw-1]; 78 tr[x].mx1=ln[cr[id]]+sm[id];tr[x].mx2=-INF; 79 tr[x].m1=ln[cr[id]]-sm[id];tr[x].m2=-INF; 80 tr[x].id1=tr[x].id2=l; 81 tr[x].lc=tr[x].rc=0; 82 } 83 else 84 { 85 LL mid=(l+r)>>1; 86 tr[x].lc=build(l,mid,nw); 87 tr[x].rc=build(mid+1,r,nw); 88 upd(x); 89 } 90 return x; 91 } 92 93 LL g[Maxn]; 94 void get_l(LL x,LL ff) 95 { 96 ln[x]=0;LL mx1=0,mx2=0; 97 g[x]=0; 98 for(LL i=first[x];i;i=t[i].next) if(t[i].y!=ff&&vis[t[i].y]) 99 { 100 LL y=t[i].y; 101 get_l(y,x); 102 if(ln[y]+t[i].c>mx1) mx2=mx1,mx1=ln[y]+t[i].c; 103 else if(ln[y]+t[i].c>mx2) mx2=ln[y]+t[i].c; 104 g[x]=mymax(g[x],g[y]); 105 } 106 g[x]=mymax(g[x],mx1+mx2); 107 ln[x]=mx1; 108 } 109 110 void change(LL x,LL y,LL nw) 111 { 112 if(tr[x].l==tr[x].r) 113 { 114 LL id=y+rr[nw-1]; 115 tr[x].mx1=sm[id]+ln[cr[id]]; 116 tr[x].m1=ln[cr[id]]-sm[id]; 117 return; 118 } 119 LL mid=(tr[x].l+tr[x].r)>>1; 120 if(y<=mid) change(tr[x].lc,y,nw); 121 else change(tr[x].rc,y,nw); 122 upd(x); 123 } 124 125 LL get_ans() 126 { 127 if(tr[1].id1!=tr[1].id2) return tr[1].mx1+tr[1].m1; 128 else return mymax(tr[1].mx1+tr[1].m2,tr[1].mx2+tr[1].m1); 129 } 130 131 int main() 132 { 133 scanf("%lld",&n); 134 len=0; 135 for(LL i=1;i<=n;i++) fa[i]=i; 136 LL cnt=0; 137 for(LL i=1;i<=n;i++) 138 { 139 LL x,y,c; 140 scanf("%lld%lld%lld",&x,&y,&c); 141 if(ffa(x)==ffa(y)) 142 { 143 r1[++cnt]=x;r2[cnt]=y; 144 nc[cnt]=c; 145 } 146 else 147 { 148 fa[ffa(x)]=ffa(y); 149 ins(x,y,c);ins(y,x,c); 150 } 151 152 } 153 cr[0]=0;rr[0]=0; 154 for(LL i=1;i<=cnt;i++) 155 { 156 dfs(r1[i],0,i); 157 rr[i]=rr[i-1]+cr[0]; 158 } 159 memset(vis,1,sizeof(vis)); 160 for(LL i=1;i<=cr[0];i++) vis[cr[i]]=0; 161 LL ans=0; 162 for(LL i=1;i<=cr[0];i++) 163 { 164 get_l(cr[i],0); 165 ans=mymax(ans,g[cr[i]]); 166 } 167 for(LL i=1;i<=cnt;i++) 168 { 169 sm[rr[i-1]+1]=0; 170 LL mn=INF; 171 172 for(LL j=rr[i-1]+2;j<=rr[i];j++) sm[j]=sm[j-1]+cc[j]; 173 174 build(1,rr[i]-rr[i-1],i); 175 mn=mymin(mn,get_ans()); 176 for(LL j=rr[i-1]+1;j<rr[i];j++) 177 { 178 LL p=j,q=p-1; 179 if(j==rr[i-1]+1) q=rr[i]; 180 sm[p]=sm[q]+cc[p]; 181 182 change(1,p-rr[i-1],i); 183 mn=mymin(mn,get_ans()); 184 } 185 ans=mymax(ans,mn); 186 } 187 printf("%.1lf\n",ans*1.0/2); 188 return 0; 189 }
2017-03-25 11:57:32