Cow Relays
Time Limit: 1000MS |
| Memory Limit: 65536K |
Total Submissions: 6793 |
| Accepted: 2660 |
Description
For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race using the T (2 ≤ T ≤ 100) cow trails throughout the pasture.
Each trail connects two different intersections (1 ≤ I1i ≤ 1,000; 1 ≤ I2i ≤ 1,000), each of which is the termination for at least two trails. The cows know the lengthi of each trail (1 ≤ lengthi ≤ 1,000), the two intersections the trail connects, and they know that no two intersections are directly connected by two different trails. The trails form a structure known mathematically as a graph.
To run the relay, the N cows position themselves at various intersections (some intersections might have more than one cow). They must position themselves properly so that they can hand off the baton cow-by-cow and end up at the proper finishing place.
Write a program to help position the cows. Find the shortest path that connects the starting intersection (S) and the ending intersection (E) and traverses exactly N cow trails.
Input
* Line 1: Four space-separated integers: N, T, S, and E
* Lines 2..T+1: Line i+1 describes trail i with three space-separated integers: lengthi , I1i , and I2i
Output
* Line 1: A single integer that is the shortest distance from intersection S to intersection E that traverses exactly N cow trails.
Sample Input
2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
Sample Output
10
Source
1、首先我们要理解这样一个问题,如果a【i】【j】表示图的初始邻接矩阵,b【i】【j】==a【i】【j】;
如果c【j】【k】=min(c【j】【k】,a【j】【i】+b【i】【k】){应用Floyd求最短路},其实不难理解,c【】【】得到的邻接矩阵是从b中拿出一条边,从a中拿出一条边构成的,那么如果初始a和
b就是邻接矩阵,那么c【i】【j】现在表示的含义就是从i到j一共经过两条边的最短路。
2、那么推广,如果现在让a【i】【j】=c【i】【j】,那么现在a【i】【j】现在表示的含义就是从i到j一共经过两条边的最短路。此时b【i】【j】不变,还是图的邻接矩阵,如果这时候c【j】【k】=min(c【j】【k】,a【j】【i】+b【i】【k】){应用Floyd求最短路}.那么c【】【】得到的邻接矩阵也是从a中拿出一条边,从b中拿出一条边构成的,然而这时候a中的一条边,其实相当于两条边,那么:c【i】【j】现在表示的含义就是从i到j一共经过三条边的最短路。
3、依次类推,如果需要经过k条边的从i到j的最短路,那么就进行k-1次上述过程即可。因为k可能比较大,而且每一次进行Floyd也是一个不小的开销,所以这k-1次乘法我们用快速幂的方式优化,最终得到正解。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<stdio.h>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
int head[100000];
struct EdgeNode
{
int to;
int w;
int next;
}e[1000000];
int dis3[1005][1005];
int dis[1005][1005];
int dis2[1005][1005];
int q,m,ss,ee,n,cont;
void Floyd(int dis[1005][1005],int dis2[1005][1005])
{
memset(dis3,0x3f3f3f3f,sizeof(dis3));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
dis3[j][k]=min(dis3[j][k],dis[j][i]+dis2[i][k]);
}
}
}
}
void init()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dis[i][j]=dis3[i][j];
}
}
}
void init2()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dis2[i][j]=dis3[i][j];
}
}
}
void Slove(int k)
{
while(k)
{
if(k%2==1)
{
Floyd(dis,dis2);
init();
}
k/=2;
Floyd(dis2,dis2);
init2();
}
}
int main()
{
while(~scanf("%d%d%d%d",&q,&m,&ss,&ee))
{
n=1;
map<int,int >mp;
memset(dis,0x3f3f3f3f,sizeof(dis));
memset(dis2,0x3f3f3f3f,sizeof(dis2));
for(int i=0;i<m;i++)
{
int x,y,w;
scanf("%d%d%d",&w,&x,&y);
if(mp[x]==0)
{
mp[x]=n++;
}
if(mp[y]==0)
{
mp[y]=n++;
}
x=mp[x];y=mp[y];
dis[x][y]=dis[y][x]=w;
dis2[x][y]=dis2[y][x]=w;
}
Slove(q-1);
printf("%d\n",dis[mp[ss]][mp[ee]]);
}
}