洛谷P2491消防
真心地,這一道題我照著題解抄都抄錯了
然後我就WA的一聲哭了出來
我是想練習樹的直徑結果實在是找不到題目了於是就用這玩意來練手…
結果… 我好像是在debug的時候吧題解直接複製了一遍…
題目描述
某個國家有n個城市,這n個城市中任意兩個都連通且有唯一一條路徑,每條連通兩個城市的道路的長度為zi(zi<=1000)。
這個國家的人對火焰有超越宇宙的熱情,所以這個國家最興旺的行業是消防業。由於政府對國民的熱情忍無可忍(大量的消防經費開銷)可是卻又無可奈何(總統競選的國民支援率),所以只能想盡方法提高消防能力。
現在這個國家的經費足以在一條邊長度和不超過s的路徑(兩端都是城市)上建立消防樞紐,為了儘量提高樞紐的利用率,要求其他所有城市到這條路徑的距離的最大值最小。
你受命監管這個專案,你當然需要知道應該把樞紐建立在什麼位置上。
輸入輸出格式
輸入格式: 輸入包含n行:
第1行,兩個正整數n和s,中間用一個空格隔開。其中n為城市的個數,s為路徑長度的上界。設結點編號以此為1,2,……,n。
從第2行到第n行,每行給出3個用空格隔開的正整數,依次表示每一條邊的兩個端點編號和長度。例如,“2 4 7”表示連線結點2與4的邊的長度為7。
輸出格式: 輸出包含一個非負整數,即所有城市到選擇的路徑的最大值,當然這個最大值必須是所有方案中最小的。
輸入輸出樣例
輸入樣例#1: 5 2 1 2 5 2 3 2 2 4 4 2 5 3 輸出樣例#1: 5 輸入樣例#2: 8 6 1 3 2 2 3 2 3 4 6 4 5 3 4 6 4 4 7 2 7 8 3 輸出樣例#2: 5 說明
【資料規模和約定】
對於20%的資料,n<=300。
對於50%的資料,n<=3000。
對於100%的資料,n<=300000,邊長小等於1000。
code
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#define maxn 710000
using namespace std ;
int read() ;
int n , m , s;
struct tree{
int x , y , z , next ;
}a[maxn] ;
int t ;int cnt ;
int head[maxn] , vis[maxn] , dis[maxn] ;
void add (int x , int y , int z) ;
int root , l , r , ans = 99999999 , sum ;
int f[maxn][40] , dep[maxn] ;
int lca(int x , int y) ;int tot ;
void init() ;
void dfs1(int u,int fa) ;
void dfs2(int u,int fa) ;
int main() {
n=read();s=read();
for(int i=1;i<n;i++)
{
int x , y , z ;
x=read();y=read();z=read();
add(x,y,z);add(y,x,z);
}
dfs1(1,0);
for(int i=1;i<=n;i++)
{
if(!root||dis[i]>dis[root]) root=i;
}
memset(dis,0,sizeof(dis));
dep[root]=1;dfs2(root,0);
for(int i=1;i<=n;i++)
{
if(!t||dis[i]>dis[t]) t=i;
}
init();
l=t;r=t;vis[t]=1;
// n = read() , s = read() ;
// for(int i = 1 ; i <= n-1 ; i ++) {
// int x , y , z ;
// x = read() , y = read(), z = read() ;
// add(x,y,z) ;
// add(y,x,z) ;
// }
// dfs1(1,0) ;
// for(int i = 1 ; i <= 0 ; i ++) {
// if(!root||dis[i] > dis[root]) root = i ;
// }
// memset(dis,0,sizeof(dis)) ;
// dep[root] = 1 ;
// dfs2(root,0) ;
// for(int i = 1 ; i <= n ; i ++) {
// if(!tot||dis[i] > dis[tot]) tot = i ;
// }
// init () ;
// int l , r ;
// l = tot , r = tot ; vis[tot] = 1 ;
// while(l != 0) {
// sum = 0 ;
// if(dis[r] - dis[l] > s) {
// vis[r] = 0 ;
// r = f[r][0] ;
// vis[r] = 1 ;
// }else while (dis[r] - dis[l] <= s && l != 0) {
// l = f[l][0] ;vis[l] = 1 ;
// }int rlca ;
// for(int i = 1 ; i <= n ; i ++) {
// if(vis[i]) continue ;
// int lca1 = lca(l,i) , lca2 = lca(r,i) ;
// if(dep[lca1] > dep[lca2]) rlca = lca1 ;
// else rlca = lca2 ;
// if(dep[rlca] < dep[l]) {
// sum = max(sum,dis[i]-2*dis[rlca]) ;
// }else sum = max(sum,dis[i]-dis[rlca]) ;
// ans = min(ans,sum) ;
// l = f[l][0] ;
// vis[l] = 1 ;
// }
// }
while(l!=0)
{
sum=0;
if(dis[r]-dis[l]>s)
{
vis[r]=0;r=f[r][0];vis[r]=1;
}
else
{
while(dis[r]-dis[l]<=s&&l!=0) {l=f[l][0];vis[l]=1;}
int rlca;
for(int i=1;i<=n;i++)
{
if(vis[i]) continue;
int lca1=lca(l,i),lca2=lca(r,i);
if(dep[lca1]>dep[lca2]) rlca=lca1;
else rlca=lca2;
if(dep[rlca]<dep[l])
{
sum=max(sum,dis[l]+dis[i]-2*dis[rlca]);
}
else sum=max(sum,dis[i]-dis[rlca]);
}
ans=min(ans,sum);
l=f[l][0];vis[l]=1;
}
}
cout << ans << endl ;
return 0;
}
//void dfs2(int u , int fa) {
// for(int i = head[u] ; i ; i = a[i].next) {
// int v = a[i].y ;
// if(v == fa) continue ;
// dis[v] = dis[u] + a[i].z ;
// f[v][0] = u ;
// dep[v] = dep[u] + 1 ;
// dfs2(v,u) ;
// }
//}
void dfs2(int k,int fa){
for(int i=head[k];i;i=a[i].next){
int v=a[i].y;
if(v==fa) continue;
dis[v]=dis[k]+a[i].z;f[v][0]=k;dep[v]=dep[k]+1;
dfs2(v,k);
}
}
//void dfs1(int u ,int fa) {
// for(int i = head[u] ; i ; i = a[i].next) {
// int v = a[i].y ;
// if(v == fa) continue ;
// dis[v] = a[i].z + dis[u] ;
// dfs1(v,u) ;
// }
//}
void dfs1(int k,int fa){
for(int i=head[k];i;i=a[i].next){
int v=a[i].y;
if(v==fa) continue;
dis[v]=dis[k]+a[i].z;
dfs1(v,k);
}
}
//int lca(int x , int y) {
// if(dep[x] < dep[y]) {
// swap(x,y) ;
// }
// for(int i = 20 ; i >= 0 ; i --) {
// if(dep[f[x][i]] >= dep[y]) x= f[x][i] ;
// }
// if(x == y) return x ;
// for(int i = 20 ; i >= 0 ; i --) {
// if(f[x][i] != f[y][i])
// x = f[x][i] , y = f[y][i] ;
// }
// return f[x][0] ;
//}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=19;i>=0;i--)
{
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
}
if(x==y) return x;
for(int i=19;i>=0;i--)
{
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
}
return f[x][0];
}
//void init () {
// for(int i = 1 ; i <= 20 ; i ++){
// for(int j = 1 ; j <= n ; j ++) {
// f[j][i] = f[f[j][i-1]][i-1] ;
// }
// }
//}
void init()
{
for(int i=1;i<=20;i++)
{
for(int j=1;j<=n;j++)
{
f[j][i]=f[f[j][i-1]][i-1];
}
}
}
//void add(int x , int y , int z) {
// a[++t].x = x ;
// a[t].y = y ;
// a[t].z = z ;
// a[t].next = head[x] ;
// head[x] = t ;
//}
void add(int x,int y,int z)
{
cnt++;
a[cnt].y=y;
a[cnt].next=head[x];
a[cnt].z=z;
head[x]=cnt;
}
int read() {
int x = 0;int f = 1 ; char s = getchar() ;
while(s>'9'||s<'0') {if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0') {x=x*10+(s-'0');s=getchar();}
return x*f ;
}
程式碼很亂,可能與L_Y_T的懶癌有關係…
凌亂的215行程式碼…
完結撒金坷垃!!