186. [USACO Oct08] 牧场旅行 (第三次考试大整理)
186. [USACO Oct08] 牧场旅行
输入文件:pwalk.in 输出文件:pwalk.out 简单对比
时间限制:1
s 内存限制:128 MB
n个被自然地编号为1..n奶牛(1<=n<=1000)正在同样被方便的编号为1..n的n个牧场中吃草。更加自然而方便的是,第i个奶牛就在第i个牧场中吃草。
其中的一些对牧场被总共的n-1条双向通道的一条连接。奶牛可以通过通道。第i条通道连接的两个牧场是A_i和B_i(1<=A_i<=N;1<=B_i<=N)其长度是L_i(1<=L_i<=10000)。
通道只会连接两个不同的牧场,所以这些通道使得整个牧场构成了一棵树。
奶牛们是好交际的希望能够经常的访问别的奶牛。急切地,它们希望你能通过告诉它们Q(1<=Q<=1000)对牧场的路径来帮助他们安排旅行。(这里将有Q个询问,p1,p2(1<=p1<=n;1<=p1<=n))
问题名称:
pwalk
输入格式:
- 第1行:两个用空格隔开的整数:n和Q
- 第2..n行:第i+1行包含三个用空格隔开的整数:A_i,B_i和L_i
- 第n+1..N+Q行:每行包含两个用空格隔开的整数,代表两个不同的牧场,p1和p2
输入样例(file pwalk.in):
4 2
2 1 2
4 3 2
1 4 3
1 2
3 2
输出格式:
- 第1..Q行:行i包含第i个询问的答案。
输出样例:
2
7
输出说明:
询问1:牧场1和牧场2的路径长度为2。 询问2:3->4->1->2;总长为7。
思路:
就是裸的spfa!!!
①90代码(弗洛伊德):
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define M 1005 5 6 using namespace std; 7 8 int map[M][M]; 9 int n,q,x,y,w; 10 11 int main() 12 { 13 //freopen("pwalk.in","r",stdin); 14 //freopen("pwalk.out","w",stdout); 15 memset(map,10001,sizeof(map)); 16 cin>>n>>q; 17 for(int i=1;i<=n-1;i++) 18 { 19 scanf("%d%d%d",&x,&y,&w); 20 map[x][y]=map[y][x]=w; 21 } 22 for(int k=1;k<=n;k++) 23 for(int i=1;i<=n;i++) 24 for(int j=1;j<=n;j++) 25 { 26 if(map[i][j]>map[i][k]+map[k][j]) 27 map[i][j]=map[i][k]+map[k][j]; 28 } 29 for(int i=1;i<=q;i++) 30 { 31 scanf("%d%d",&x,&y); 32 cout<<map[x][y]<<endl; 33 } 34 //fclose(stdin); 35 //fclose(stdout); 36 return 0; 37 }
②改进后的代码(spfa):
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define MAXN 1001 7 #define maxn 0x7fffffff 8 9 using namespace std; 10 11 struct node 12 { 13 int u; 14 int v; 15 int w; 16 int next; 17 }edge[MAXN]; 18 19 int head[MAXN],dis[MAXN]; 20 int n,q,vis[MAXN],num=1; 21 22 int spfa(int bg,int ed)//如题,裸的spfa 23 { 24 for(int i=1;i<=n;i++) dis[i]=maxn; 25 memset(vis,0,sizeof(vis)); 26 queue<int>q; 27 q.push(bg); 28 dis[bg]=0; 29 vis[bg]=1; 30 while(q.size()!=0) 31 { 32 int p=q.front(); 33 q.pop(); 34 for(int i=head[p];i!=-1;i=edge[i].next) 35 { 36 int to=edge[i].v; 37 if(dis[to]>dis[p]+edge[i].w) 38 { 39 dis[to]=dis[p]+edge[i].w; 40 if(vis[to]==0) 41 { 42 q.push(to); 43 vis[to]=1; //必须要进行标记!!! 44 } 45 } 46 } 47 } 48 return dis[ed]; 49 } 50 int main() 51 { 52 //freopen("pwalk.in","r",stdin); 53 //freopen("pwalk.out","w",stdout); 54 scanf("%d%d",&n,&q); 55 for(int i=1;i<=n;i++)head[i]=-1;//进行初始化 56 for(int i=1;i<n;i++) 57 { 58 scanf("%d%d%d",&edge[num].u,&edge[num].v,&edge[num].w); 59 edge[num].next=head[edge[num].u]; 60 head[edge[num].u]=num++; 61 edge[num].v=edge[num-1].u; 62 edge[num].u=edge[num-1].v; 63 edge[num].w=edge[num-1].w; 64 edge[num].next=head[edge[num].u]; 65 head[edge[num].u]=num++; 66 } 67 for(int i=1;i<=q;i++)//进行输出 68 { 69 int bg; 70 int ed; 71 scanf("%d%d",&bg,&ed); 72 printf("%d\n",spfa(bg,ed)); 73 } 74 return 0; 75 }