* * * * 首先,感谢pxgg一直以来的支持和帮助* * * * *
题目链接
* 题目大意,N头奶牛,从各自地点(就是他们的编号1 , 2 , -- N),沿着一条单向路,前去X(1 <= X<= N)地,
* 参加party,party后,N头奶牛,沿着一条单向路回到原地。问来回需要最小的时间。
数据范围:1 ≤ N ≤ 1000 ,1 ≤ M ≤ 100 , 000 ,Ti,1 ≤ Ti ≤ 100 ;依次为点的数目,边的数目,一条路所需时间。
时间要求:2000 ms;
所用算法:Floyd, O ( N^ 3 ) 超时;bellman,O(N* M),超时;* * dijkstra* * ,优化前,O(N^ 2 ), 可跑,* * 优化* * 后,O((N+ M)log2 ( N) ),强。
题目要求:( 1 ) 求出n头奶牛到一个地点的距离sum1,
( 2 ) 求出n头奶牛从一个地点到n个地点的距离sum2。
( 3 ) 输出sum1+ sum2;
第(2 )个问题容易解决,就是跑一边dijkstra,算出X点到n个点的最小距离的和。
第(1 )个问题求的是n个点到1 个点X的距离,我们这样想:
有4 的点,1 ,2 ,3 ,4 ,要去2 号点,已知最短路线如下:
这些路径是单向的,如果我们求每个点到2 的最短距离,最多跑n次,dijkstra复杂度也不行,肯定会超。
路径的长度是一定的,那么我们这样想,现在让牛走到2 号点的时候沿着原路返回。走的这些距离就是sum1;
1 -- > 3 -- > 2 ;
2 ;
3 -- > 4 -- > 2 ;
4 -- > 1 -- > 2 ;
这些路径就成了:
2 -- > 3 -- > 1 ;
2 ;
2 -- > 4 -- > 3 ;
2 -- > 1 -- > 4 ;
我们的问题又变成了求2 号点到各个顶点的距离。
* * * 但是要把所有的边都逆向处理,因为如果不处理的话,怎么求啊,哈哈哈哈哈哈哈哈哈。* * *
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int num_e= 100000 + 10 ;
const int num_p= 1010 ;
const int inf= 0x3f3f3f3f ;
struct node
{
int v, w, next;
node ( ) { } ;
node ( int a, int b)
{
v= a; w= b;
}
bool operator < ( const node & s) const
{
return w > s. w;
}
} edge[ num_e] ;
int head[ num_p] ;
int from[ num_e] , to[ num_e] , worth[ num_e] ;
int date[ 2 ] [ num_e] ;
int n, m, x, cnt;
void int_i ( void )
{
cnt= 0 ;
for ( int j= 1 ; j<= n; j++ )
head[ j] = 0 ;
return ;
}
void addedge ( int a, int b, int c)
{
edge[ ++ cnt] . v= b;
edge[ cnt] . w= c;
edge[ cnt] . next= head[ a] ;
head[ a] = cnt;
return ;
}
void dijkstra ( int g)
{
int dis[ n+ 1 ] ;
int book[ n+ 1 ] ;
for ( int i= 1 ; i<= n; i++ )
{
dis[ i] = inf;
book[ i] = 0 ;
}
dis[ x] = 0 ;
priority_queue< node> q;
q. push ( node ( x, 0 ) ) ;
while ( ! q. empty ( ) )
{
node x= q. top ( ) ; q. pop ( ) ;
if ( book[ x. v] )
continue ;
book[ x. v] = 1 ;
for ( int i= head[ x. v] ; i; i= edge[ i] . next)
{
int y= edge[ i] . v;
if ( book[ y] ) continue ;
if ( dis[ y] > x. w + edge[ i] . w)
{
dis[ y] = x. w + edge[ i] . w;
q. push ( node ( y, dis[ y] ) ) ;
}
}
}
for ( int i= 1 ; i<= n; i++ )
{
date[ g] [ i] = dis[ i] ;
}
return ;
}
int main ( )
{
scanf ( "%d%d%d" , & n, & m, & x) ;
int_i ( ) ;
for ( int i= 1 ; i<= m; i++ )
{
scanf ( "%d%d%d" , & from[ i] , & to[ i] , & worth[ i] ) ;
addedge ( from[ i] , to[ i] , worth[ i] ) ;
}
dijkstra ( 0 ) ;
int_i ( ) ;
for ( int i= 1 ; i<= m; i++ )
{
addedge ( to[ i] , from[ i] , worth[ i] ) ;
}
dijkstra ( 1 ) ;
int maxm= 0 ;
for ( int i= 1 ; i<= n; i++ )
maxm= max ( maxm, date[ 0 ] [ i] + date[ 1 ] [ i] ) ;
printf ( "%d\n" , maxm) ;
return 0 ;
}
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int inf= 0x3f3f3f3f ;
const int num= 1010 ;
struct edge
{
int u, v, w;
edge ( int a, int b, int c)
{
u= a; v= b; w= c;
}
} ;
vector< edge> e[ num] ;
int from[ num] , to[ num] , time[ num] ;
int date[ 2 ] [ num] ;
struct point
{
int id, n_dis;
point ( int a, int b)
{
id= a; n_dis= b;
}
bool operator < ( const point & a) const
{
return n_dis > a. n_dis;
}
} ;
void dijkstra ( int g, int x, int n)
{
int dis[ num] ;
bool book[ num] ;
for ( int i= 1 ; i<= n; i++ )
{
dis[ i] = inf;
book[ i] = false;
}
dis[ x] = 0 ;
priority_queue< point> q;
q. push ( point ( x, 0 ) ) ;
while ( ! q. empty ( ) )
{
point x= q. top ( ) ;
q. pop ( ) ;
if ( book[ x. id] )
continue ;
book[ x. id] = true;
for ( int i= 0 ; i< e[ x. id] . size ( ) ; i++ )
{
edge y= e[ x. id] [ i] ;
if ( book[ y. v] )
continue ;
if ( dis[ y. v] > x. n_dis + y. w)
{
dis[ y. v] = x. n_dis + y. w;
q. push ( point ( y. v, dis[ y. v] ) ) ;
}
}
}
for ( int i= 1 ; i<= n; i++ )
date[ g] [ i] = dis[ i] ;
return ;
}
int main ( )
{
int x, n, m;
int u, v, w;
int sum= 0 ;
scanf ( "%d%d%d" , & n, & m, & x) ;
for ( int i= 1 ; i<= n; i++ )
{
e[ i] . clear ( ) ;
}
for ( int i= 1 ; i<= m; i++ )
{
scanf ( "%d%d%d" , & from[ i] , & to[ i] , & time[ i] ) ;
e[ to[ i] ] . push_back ( edge ( to[ i] , from[ i] , time[ i] ) ) ;
}
dijkstra ( 0 , x, n) ;
for ( int i= 1 ; i<= n; i++ )
{
e[ i] . clear ( ) ;
}
for ( int i= 1 ; i<= m; i++ )
{
e[ from[ i] ] . push_back ( edge ( from[ i] , to[ i] , time[ i] ) ) ;
}
dijkstra ( 1 , x, n) ;
sum= 0 ;
for ( int i= 1 ; i<= n; i++ )
sum= max ( date[ 0 ] [ i] + date[ 1 ] [ i] , sum) ;
printf ( "%d\n" , sum) ;
return 0 ;
}