Codevs 2370 小机房的树

来源:互联网 发布:pcb软件 最好 编辑:程序博客网 时间:2024/05/21 10:55
时间限制: 1 s  空间限制: 256000 KB   题目等级 : 钻石 Diamond
题目描述 Description

小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上。有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力。已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力

输入描述 Input Description
第一行一个n,接下来n-1行每一行有三个整数u,v, c 。表示节点 u 爬到节点 v 需要花费 c 的精力。
第n+1行有一个整数m表示有m次询问。接下来m行每一行有两个整数 u ,v 表示两只虫子所在的节点
输出描述 Output Description

一共有m行,每一行一个整数,表示对于该次询问所得出的最短距离。

样例输入 Sample Input

3

1 0 1

2 0 1

3

1 0

2 0

1 2

样例输出 Sample Output

1

1

2

数据范围及提示 Data Size & Hint

1<=n<=50000, 1<=m<=75000, 0<=c<=1000

50分WA代码:

 1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 using namespace std; 6 #define maxn 60010 7 #define S 16 8 int n,m,a[maxn],deep[maxn],fa[maxn][S+10],ans,p1,p2,head[maxn],num,dis[maxn]; 9 struct node{10     int u,v,pre,value;//  dis[i] 数组 从 i到根节点的最短距离 11 }e[maxn*2];12 void dfs(int u,int di)13 {14     dis[u]=di;/*统计u到根节点的距离*/15     for(int l=head[u];l;l=e[l].pre)16     {17         if(!deep[e[l].v])18         {19             deep[e[l].v]=deep[u]+1;/*处理孩子的深度*/20             fa[e[l].v][0]=u;/*初始化p数组*/21             dfs(e[l].v,di+e[l].value);22         }23     }24 }25 void get_fa()26 {27     for(int j=1;j<=S;j++)28         for(int i=1;i<=n;i++)29             fa[i][j]=fa[fa[i][j-1]][j-1];30 }31 int LCA(int a,int b)32 {33     if(deep[a]<deep[b])swap(a,b); 34     for(int j=S;j>=0;j--)35       if((deep[a]-(1<<j))>=deep[b])36         a=fa[a][j];37     if(a==b)return a;38     for(int i=S;i>=0;i--)39       if(fa[a][i]!=fa[b][i])40         {41           a=fa[a][i];42           b=fa[b][i];43         }44     return fa[a][0];45 }46 void add_egre(int from,int to,int value)47 {48     num++;49     e[num].u=from;50     e[num].v=to;51     e[num].value=value;52     e[num].pre=head[from];53     head[from]=num;54 }55 int main()56 {57     scanf("%d",&n);58     for(int i=1,x,y,z;i<n;i++)59     {60         scanf("%d%d%d",&x,&y,&z);61         add_egre(x,y,z);add_egre(y,x,z);62     }63     memset(dis,0,sizeof(dis));64     memset(deep,0,sizeof(deep));65     dfs(1,0);66     get_fa();scanf("%d",&m);67     for(int i=1;i<=m;i++)68     {69         scanf("%d%d",&p1,&p2);70         int k=LCA(p1,p2);71         ans=dis[p1]+dis[p2]-2*dis[k];// deep shendu72         printf("%d\n",ans);73     }74     return 0;75 }

赶脚思路没毛病~~~

AC代码:

 1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 using namespace std; 6 #define maxn 60010 7 #define S 16 8 int n,m,a[maxn],deep[maxn],fa[maxn][20],ans,p1,p2,head[maxn],num;long long dis[maxn]; 9 struct node{10     int u,v,pre,value;//  dis[i] 数组 从 i到根节点的最短距离 11 }e[maxn*4];12 void dfs(int u,long long di)13 {14     dis[u]=di;/*处理u到根节点的距离*/15     for(int l=head[u];l;l=e[l].pre)16     {17         if(!deep[e[l].v])18         {19             deep[e[l].v]=deep[u]+1;/*处理孩子的深度*/20             fa[e[l].v][0]=u;/*初始化fa数组*/21             dfs(e[l].v,di+e[l].value);22         }23     }24 }25 int LCA(int a,int b)26 {27     int i,j;28     if(deep[a]<deep[b]) swap(a,b); 29     for(i=0;(1<<i)<=deep[a];++i);30          i--;31     for(j=i;j>=0;j--)32       if((deep[a]-(1<<j))>=deep[b])33         a=fa[a][j];34     if(a==b)return a;35     for(j=i;j>=0;j--)36       if(fa[a][j]!=-1&&fa[a][j]!=fa[b][j])37         {38           a=fa[a][j];39           b=fa[b][j];40         }41     return fa[a][0];42 }43 void init()44 {45      int i,j;46      for(j=1;(1<<j)<n;j++)47        for(int i=0;i<n;++i)48         if(fa[i][j]=-1)49           fa[i][j]=fa[fa[i][j-1]][j-1];/*DP处理出i的所有2^j祖先是谁*/50 }51 void add_egre(int from,int to,int value)52 {53     num++;54     e[num].u=from;55     e[num].v=to;56     e[num].value=value;57     e[num].pre=head[from];58     head[from]=num;59 }60 int main()61 {62     scanf("%d",&n);63     for(int i=1,x,y,z;i<n;i++)64     {65         scanf("%d%d%d",&x,&y,&z);66         add_egre(x,y,z);add_egre(y,x,z);67     }68     memset(fa,-1,sizeof(fa));69     deep[0]=0;70     dfs(0,0);71     init(); 72     scanf("%d",&m);73     for(int i=1;i<=m;i++)74     {75         scanf("%d%d",&p1,&p2);76         int k=LCA(p1,p2);77         ans=dis[p1]+dis[p2]-2*dis[k];78         printf("%d\n",ans);79     }80     return 0;81 }

 

0 0
原创粉丝点击