kuangbin专题四 D题 Silver Cow Party(POJ3268)
题目链接:http://poj.org/problem?id=3268
题意:有 编号 1 -> n 的牛,牛之间有 m 条边 ,经过每条边需要一定的时间 ti(权值),输出所有牛里面 去源点 然后返回的 最小的 最大时间
给出 源点 x
1 ≤ N ≤ 1000 1 ≤ M ≤ 100,000 1 ≤ Ti ≤ 100
思路:(单源点最短路 ,双向搜索),以 源点 x 为起点正向 Dijksual()搜索处理 最短路 , 以 x 为源点 反向 Dijksual()搜索处理最短路
注意:dis[i] 数组存放的是 源点 到 点 i 的最小权重 还有 最后 本身到本身是不合法的 (后面有注释)
AC代码 :
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std ; #define maxn 1006 #define inf 99999999 bool visit1[maxn] ; bool visit2[maxn] ; int map[maxn][maxn] ; int dis1[maxn] ; int dis2[maxn] ; int n , m , x ; void dijksual(int s) { memset(visit1 , 0 , sizeof(visit1)) ; memset(visit2 , 0 , sizeof(visit2)) ; visit1[s] = visit2[s] = 1 ; for (int i = 1 ; i <= n ; i++) { dis1[i] = map[s][i] ; // 正向 dis2[i] = map[i][s] ; //反向 } int v1 , v2 ; for (int i = 1 ; i <= n ; i++) { int min_num1 = inf ; int min_num2 = inf ; for (int j = 1 ; j <= n ; j++) { if(!visit1[j]&&dis1[j] < min_num1){ min_num1 = dis1[j] ; v1 = j ; } if(!visit2[j] && dis2[j] < min_num2){ min_num2 = dis2[j] ; v2 = j ; } } visit1[v1] = 1 ; visit2[v2] = 1 ; for(int j=1 ; j<=n ; j++){ if(!visit1[j] && dis1[j] > dis1[v1] + map[v1][j]){//正向维护 dis1[j] = dis1[v1] + map[v1][j] ; } if(!visit2[j] && dis2[j] > dis2[v2] + map[j][v2]) {//反向维护 dis2[j] = dis2[v2] + map[j][v2] ; } } } return; } int main() { int a , b , c ; //freopen("1.txt" , "r" , stdin) ; while (~scanf("%d%d%d" , &n , &m , &x)) { //memset(map , 0 , sizeof(map)) ; for (int i = 1 ; i <= n ; i++) { for (int j = 1 ; j <= n ; j++) { map[i][j] = inf ; } } for (int i = 1 ; i <= m ; i++) { scanf("%d%d%d" , &a , &b , &c) ; map[a][b] = c ; } dijksual(x) ; int ans = 0 ; for (int i = 1 ; i <= n ; i++) { // 会出现源点 x 的 dis1[x] 和 dis2[x] 值为 inf 的现象 (逻辑上是不合法的) //if (dis1[i]<inf&&dis2[i]<inf if(i != x && dis1[i] + dis2[i] > ans ) { ans = dis1[i] + dis2[i] ; } } printf("%d\n" , ans) ; } return 0 ; }