bzoj 3743
這道題用到了4個dfs,分別是找出所有家的最小生成樹,找出一點距離樹的最小距離,找出每個點兒子距離的最大值(不包括父親,也就是指不包括根節點的子樹),用父親的值來更新自己
因為我們可以知道:如果我們在樹上,那么最短的距離就是樹的長度的兩倍-距自己最遠的點的距離,當我們不在樹上時,就得先走到樹上(這條路徑是唯一的),然后再重復剛才的過程
找出生成樹比較簡單,重點是找出距樹上一點最遠的點的距離,這里先找出除了父親之外每個子樹的距離,求出最大和第二,然后再用父親更新自己的距離,很難想到
#include<iostream> #include<stdio.h> #include<string.h> #define N 1000010 using namespace std; typedef long long ll; ll tot; int cnt=-1; int head[N],to[N],next[N],w[N],used[N],nearest_node[N]; ll dis[N],max_dis[N],sec_dis[N],min_dis[N]; int max_dis_node[N],sec_dis_node[N]; bool k[N],on_tree[N];void insert(int u,int v,int c) {next[++cnt]=head[u];head[u]=cnt;to[cnt]=v;w[cnt]=c; }ll max(ll x,ll y) {return x>y?x:y; }ll min(ll x,ll y) {return x<y?x:y; }void init() {memset(head,-1,sizeof(head));memset(to,-1,sizeof(to));memset(next,-1,sizeof(next));memset(used,0,sizeof(used));memset(on_tree,false,sizeof(on_tree));memset(min_dis,0,sizeof(min_dis));memset(nearest_node,0,sizeof(nearest_node));memset(dis,0,sizeof(dis));memset(max_dis,0,sizeof(max_dis)); }bool dfs1(int u)//找樹 {used[u]=1;for(int i=head[u];~i;i=next[i]){int v=to[i];if(!used[v]){bool f2=dfs1(v);if(f2){on_tree[u]|=f2;tot+=w[i];}dfs1(v);}}return on_tree[u]; }void dfs2(int u)//找樹距 {used[u]=1; if(on_tree[u]) nearest_node[u]=u;for(int i=head[u];~i;i=next[i]){int v=to[i]; if(!on_tree[v]&&!used[v]){min_dis[v]=min_dis[u]+w[i];nearest_node[v]=nearest_node[u];} if(!used[v]) dfs2(v);} } ll dfs3(int u)//兒子的最大距離 {used[u]=1;for(int i=head[u];~i;i=next[i]){int v=to[i];if(!used[v]&&on_tree[v]){ll dis=dfs3(v)+w[i];if(dis>max_dis[u]){sec_dis[u]=max_dis[u];max_dis[u]=dis;max_dis_node[u]=v;} else if(dis>sec_dis[u]){sec_dis[u]=dis;}}}return max_dis[u]; }void dfs4(int u,ll last_max) {used[u]=1;for(int i=head[u];~i;i=next[i]){int v=to[i]; ll temp=max(last_max,max_dis[u]);dis[u]=max(last_max,max_dis[u]);if(!used[v]&&on_tree[v]){if(max_dis_node[u]==v){ dfs4(v,max(last_max,sec_dis[u])+w[i]);}else dfs4(v,max(last_max,max_dis[u])+w[i]);}} }int main() {init();int n,k; scanf("%d%d",&n,&k);for(int i=1;i<n;i++){int u,v,c; scanf("%d%d%d",&u,&v,&c);insert(u,v,c); insert(v,u,c);}int x;for(int i=1;i<=k;i++){scanf("%d",&x); on_tree[x]=true; } dfs1(x); memset(used,0,sizeof(used));dfs2(x); memset(used,0,sizeof(used));dfs3(x); memset(used,0,sizeof(used));dfs4(x,0); /* printf("tot=%d\n",tot);printf("-------------\n");for(int i=1;i<=n;i++)printf("%d ",dis[i]);printf("\n------------\n"); */for(int i=1;i<=n;i++)printf("%lld\n",2*tot+min_dis[i]-dis[nearest_node[i]]);return 0; }?
轉載于:https://www.cnblogs.com/19992147orz/p/6058114.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
- 上一篇: 3.2.1 配置构建Angular应用—
- 下一篇: iOS学习笔记11-多线程入门