当前位置: 代码迷 >> 综合 >> 【搜索】Codeforces1016F Road Projects
  详细解决方案

【搜索】Codeforces1016F Road Projects

热度:125   发布时间:2023-09-27 06:57:10.0

分析:

额,可以把树中从1到n的那条链单独提出来,
【搜索】Codeforces1016F Road Projects

显然,如果某个点延伸出去的点不小于了2个,那么肯定连那些点(蓝色边)是最优的。因为它不会对最短路造成影响。否则只能连红色边是最优的。

显然,我们连接的点u、v是在最优条件下固定的。

无非求出这两个点罢了。这两个点满足min{ dist0?>u+distv?>ndistn?>u+distv?>0}min{dist0?>u+distv?>n,distn?>u+distv?>0}尽可能大。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 300010
using namespace std;
typedef long long ll;
vector<int> a[MAXN];
vector<ll> w[MAXN];
int spe[MAXN];
ll dist[MAXN],maxv=-1,ans;
int n,m;
bool spex=1;
void prepare(int x,int f,ll len){dist[x]=len;for(int i=0;i<a[x].size();i++){if(a[x][i]==f)continue;prepare(a[x][i],x,len+w[x][i]);}
}
int dfs(int x,int f){spe[x]=-1;bool flag=0;for(int i=0;i<a[x].size();i++){if(a[x][i]==f)continue;if(dfs(a[x][i],x)==1){spe[x]=i;flag=1;}if(spe[x]==i)continue;if((x==n||x==1)&&(a[x].size()>2||a[a[x][i]].size()>1))spex=0;if(x!=1&&x!=n&&(a[x].size()>3||a[a[x][i]].size()>1))spex=0;}if(x==n)return 1;return flag;
}
void dfs2(int x,int f,ll len){maxv=max(maxv,len);for(int i=0;i<a[x].size();i++){if(a[x][i]==f)continue;dfs2(a[x][i],x,len+w[x][i]);}
}
void dfs1(int x,int f,ll len){if(maxv!=-1&&spe[x]==-1&&x!=n)ans=max(ans,maxv+dist[x]);for(int i=0;i<a[x].size();i++){if(a[x][i]==f||i==spe[x])continue;dfs1(a[x][i],x,len+w[x][i]);}if(spe[x]!=-1){for(int i=0;i<a[x].size();i++){if(a[x][i]==f||i==spe[x])continue;dfs2(a[x][i],x,len+w[x][i]);}if(maxv!=-1)ans=max(ans,maxv+dist[a[x][spe[x]]]);maxv=max(maxv,len);dfs1(a[x][spe[x]],x,len+w[x][spe[x]]);}
}
int main(){SF("%d%d",&n,&m);int u,v;ll val;for(int i=1;i<n;i++){SF("%d%d%I64d",&u,&v,&val); a[u].push_back(v);a[v].push_back(u);w[u].push_back(val);w[v].push_back(val);}prepare(n,0,0);dfs(1,0);dfs1(1,0,0);ll len;for(int i=1;i<=m;i++){SF("%I64d",&len);if(spex)PF("%I64d\n",min(dist[1],ans+len));elsePF("%I64d\n",dist[1]);}
}
  相关解决方案