zoukankan      html  css  js  c++  java
  • POJ 3268

    来自 N (1 ≤ N ≤ 1000)个农场的奶牛的编号分别为1,2, … ,N。现在在农场 X (1 ≤ X ≤ N) 举行聚会。总共有 M (1 ≤ M ≤ 100,000) 条单向通道。路 i 需要时间 Ti 才能通过。每头牛都需要参加聚会并返回,而且它们均选择花费时间最短的路线。
    问:在所有的奶牛中,所花费的最长时间为多少?
    Input
    第一行包含三个整数N,M,X。
    在接下来的M行中,每行都包括三个整数A,B和T,表示从农场A到B需要花费时间T。

    Output

    输出奶牛所花的最大时间。

    Sample Input

    4 8 2
    1 2 4
    1 3 2
    1 4 7
    2 1 1
    2 3 5
    3 1 2
    3 4 4
    4 2 3

    Sample Output

    10

    题目大意:

    给出 n 个点,m 条边,和一个点 x ,接下来有 m 行 a b c ,表示a b 两点之间有一条权值为 c 的单向边,奶牛们要去 x 点聚会,每一头牛都走最短路,询问哪一头奶牛往返时间最长,输出这个最长时间。

    解题思路:

    正反双向建图,建两个图,跑两遍spfa即可。

    Code:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <iomanip>
    #include <sstream>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #define lowbit(x) x & (-x)
    
    using namespace std;
    
    typedef long long ll;
    typedef pair<int, int> pii;
    
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    const int N = 1e3 + 50;
    const int M = 1e5 + 50;
    
    int h[N], ne[M], w[M], e[M], idx;
    int h1[N], ne1[M], w1[M], e1[M], idx1;
    int n, m, x;
    int dis[N], dis1[N];
    int vis[N], vis1[N];
    
    void add(int a, int b, int c)//链式前向星正反建两个图
    {
    	e[idx] = b;
    	w[idx] = c;
    	ne[idx] = h[a];
    	h[a] = idx++;
    
    	e1[idx1] = a;
    	w1[idx1] = c;
    	ne1[idx1] = h1[b];
    	h1[b] = idx1++;
    }
    
    void spfa()//正着跑一遍spfa
    {
    	memset(dis, 0x3f, sizeof dis);
    	dis[x] = 0;
    
    	queue<int > q;
    	q.push(x);
    	vis[x] = true;
    
    	while (!q.empty())
    	{
    		int t = q.front();
    		q.pop();
    		vis[t] = false;
    
    		for (int i = h[t]; ~i; i = ne[i])
    		{
    			int j = e[i];
    			if (dis[t] + w[i] < dis[j])
    			{
    				dis[j] = dis[t] + w[i];
    				if (!vis[j])
    				{
    					vis[j] = true;
    					q.push(j);
    				}
    			}
    		}
    	}
    }
    
    void respfa()//反向再跑一遍
    {
    	memset(dis1, 0x3f, sizeof dis1);
    	dis1[x] = 0;
    
    	queue<int > q;
    	q.push(x);
    	vis1[x] = true;
    
    	while (!q.empty())
    	{
    		int t = q.front();
    		q.pop();
    		vis1[t] = false;
    
    		for (int i = h1[t]; ~i; i = ne1[i])
    		{
    			int j = e1[i];
    			if (dis1[t] + w1[i] < dis1[j])
    			{
    				dis1[j] = dis1[t] + w1[i];
    				if (!vis1[j])
    				{
    					vis1[j] = true;
    					q.push(j);
    				}
    			}
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d%d%d", &n, &m, &x);
    
    	memset(h, -1, sizeof h);
    	memset(h1, -1, sizeof h1);
    
    	while (m--)
    	{
    		int a, b, c;
    		scanf("%d%d%d", &a, &b, &c);
    		add(a, b, c);
    	}
    
    	spfa();
    	respfa();
    
    	int ans = -1;
    
    	for (int i = 1; i <= n; i ++)
    		if (dis[i] != inf && dis1[i] != inf)
    			ans = max(ans, dis[i] + dis1[i]);//ans取最大值,输出即可
    
    	printf("%d
    ", ans);
    
    	return 0;
    }
    
  • 相关阅读:
    猫树
    单位根反演
    区间修改区间求和
    最远点 决策单调性
    圆方树
    912. 排序数组
    1309. 解码字母到整数映射
    28. 实现 strStr()
    31. 下一个排列
    22. 括号生成
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294134.html
Copyright © 2011-2022 走看看