#include

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 ;
}

 

posted @ 2017-09-27 20:34  0一叶0知秋0  阅读(140)  评论(0编辑  收藏  举报