codevs1036商务旅行

题目描述 Description

某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。

假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。

你的任务是帮助该商人计算一下他的最短旅行时间。

 

枯燥无味的直接发代码的话,我自己都看不下去,所以我决定讲讲做法,实在做不出来的,再抄我下面的代码吧;

首先我们应该先知道怎么解,路线如下:

1-->3-->2-->5    而n可以达到30000,如果每个点都用spfa求最短距离然后再累加的话,肯定超时

因为图中没有存在环,所以肯定两点之间只存在一条路线,用lca做就妥妥过了(如果可以也能用线段树过,会的来教一下我

也就是说,只要求出1->1(求1->1是怕数据有开始第一个点不是到达1的),1->3,3->2,2->5的最近公共祖先,然后求每对顶点都最近公共祖先的距离和即可算出;

如果听不大懂没关系,我下面稍微模拟一下样例吧

 

    1

      /      \

       2          5

                    /     \

                     3      4

 

图在上面

1.先用bfs算一次顶点1到各个顶点的距离,用dis数组表示:

        1  2  3  4  5

dis    0  1  2  2  1

  求这个距离的用处,例如:2和5的最近公共祖先为1,而2到5的距离就是dis[2]-dis[1]+dis[5]-dis[1]=(dis[2]+dis[5])-2*dis[1]=2,就是2到公共祖先的距离加上5到公共祖先的距离

 

2.然后lca的做法自己百度吧,算出1--1,1--3,3--2,2--5的公共祖先,刚好都是1(,,,,)

然后算出(dis[1]+dis[1])-2*dis[1]+(dis[1]+dis[3])-2*dis[1]+(dis[3]+dis[2])-2*dis[1]+(dis[2]+dis[5])-2*dis[1] 就是答案了

最后,还有不懂的联系2602626065@qq.com,也欢迎来纠正错误,更欢迎希望神犇来带我飞

codevs上的同个题解也是我写的,就不要怀疑我抄袭了:)

 

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <vector>
  4 #include <queue>
  5 #include <cstring>
  6 using namespace std;
  7 const int _maxn=30010;
  8 vector<int> a[_maxn];
  9 vector<int> t[_maxn]; 
 10 queue<int> que;
 11 int dis[_maxn],n,m,f[_maxn];
 12 bool vis[_maxn];
 13 struct question
 14 {
 15     int u,v,ans;
 16 }b[_maxn];
 17 void read() 
 18 {
 19     int i,x,y;
 20     scanf("%d",&n);
 21     for(i=1;i<n;i++)
 22     {
 23         f[i]=i;
 24         scanf("%d%d",&x,&y);
 25         a[x].push_back(y);
 26         a[y].push_back(x);
 27     }
 28     f[n]=n;
 29     scanf("%d",&m);
 30     b[1].u=1;
 31     for(i=1;i<=m;i++)
 32     {
 33         scanf("%d",&x);
 34         b[i].v=x;
 35         t[x].push_back(i);
 36         if(i+1<=m)
 37         {
 38             b[i+1].u=x;
 39             t[x].push_back(i+1);
 40         }
 41     }
 42 }
 43 int find(int x)
 44 {
 45     return f[x]==x?x:find(f[x]);
 46 }
 47 void lca(int x,int fa)
 48 {
 49     int l=a[x].size(),i,to;
 50     for(i=0;i<l;i++)
 51     {
 52         to=a[x][i];
 53         if(to==fa)
 54             continue;
 55         lca(to,x);
 56         f[to]=x;
 57         vis[to]=true;
 58     }
 59     l=t[x].size();
 60     int xx,yy,zz;
 61     for(i=0;i<l;i++)
 62     {
 63         to=t[x][i];
 64         xx=b[to].u;
 65         yy=b[to].v;
 66         if(xx==yy)
 67             b[to].ans=xx;
 68         if(xx!=x && yy==x && vis[xx])
 69             b[to].ans=find(xx);
 70         if(xx==x && yy!=x && vis[yy])
 71             b[to].ans=find(yy);
 72     }
 73 }
 74 void bfs()
 75 {
 76     memset(vis,false,sizeof(vis));
 77     que.push(1);
 78     vis[1]=true;
 79     dis[1]=0;
 80     int i,l,from,to;
 81     while(!que.empty())
 82     {
 83         from=que.front();
 84         que.pop();
 85         l=a[from].size();
 86         for(i=0;i<l;i++)
 87         {
 88             to=a[from][i];
 89             if(!vis[to])
 90             {
 91                 dis[to]=dis[from]+1;
 92                 vis[to]=true;
 93                 que.push(to);
 94             }
 95         }
 96     }
 97 }
 98 int clac_ans()
 99 {
100     int x,y,z,sum=0;
101     for(int i=1;i<=m;i++)
102     {
103         x=b[i].u;
104         y=b[i].v;
105         z=b[i].ans;
106         sum=sum+(dis[x]+dis[y])-(dis[z]<<1);
107     }
108     return sum;
109 }
110 void work()
111 {
112     bfs();
113     memset(vis,false,sizeof(vis));
114     lca(1,1);
115     printf("%d\n",clac_ans());
116 }
117 int main()
118 {
119     read();
120     work();
121     return 0;
122 }
codevs1036

 

posted @ 2015-10-04 09:42  HELLO----WORLD  阅读(302)  评论(0编辑  收藏  举报