poj-3268 Silver Cow Party (最短路-spfa-求到同一起点,同一终点的最短路)

来源:互联网 发布:avr单片机 编辑:程序博客网 时间:2024/05/29 18:36
Silver Cow Party
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 23716 Accepted: 10826

Description

One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X ≤ N). A total of M (1 ≤ M ≤ 100,000) unidirectional (one-way roads connects pairs of farms; road i requires Ti (1 ≤ Ti ≤ 100) units of time to traverse.

Each cow must walk to the party and, when the party is over, return to her farm. Each cow is lazy and thus picks an optimal route with the shortest time. A cow's return route might be different from her original route to the party since roads are one-way.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back?

Input

Line 1: Three space-separated integers, respectively: NM, and X 
Lines 2..M+1: Line i+1 describes road i with three space-separated integers: AiBi, and Ti. The described road runs from farm Ai to farm Bi, requiring Ti time units to traverse.

Output

Line 1: One integer: the maximum of time any one cow must walk.

Sample Input

4 8 21 2 41 3 21 4 72 1 12 3 53 1 23 4 44 2 3

Sample Output

10

Hint

Cow 4 proceeds directly to the party (3 units) and returns via farms 1 and 3 (7 units), for a total of 10 time units.



题目大意:有N个农场,每个农场里有一头奶牛,现在每头奶牛都要从自己的农场出发前往编号为X的农场参加一个奶牛派对,参加派对之后再返回自己所在的农场,每头奶牛都很懒所以他们会选择最短的路径去参加派对和回家。现在已知在N个农场之间有M条单向的路,并且告诉你通过每条路所需要花费的时间,现在问在这N头奶牛哪头奶牛去参加派对和回来所需花费的时间最长,这个时间是多少?
题目思路:题目给出了终点,便是求从N个点到终点的最短路径和从终点回到各自点的最短路径,我们可以很轻易地用spfa求出从X点到其他N-1个点的最短路(也就是回程的最短路),接下来你可以选择用dijkstra或者spfa从每个点往X再求一次最短路,但是这样时间花费会比较多(由于本题数据较水,这样写也是可以过的,并不会TLE);而最好的做法是选择重新连边,将单向边的方向倒过来,这样我们再用spfa从X点向其他N-1个点跑一遍所求得的最短路就是从N点到X点的最短路了。

第一种写法耗时:
 3268Accepted928K516MSG++2162B 
第二种写法耗时
3268Accepted920K32MSG++2248B 
AC代码如下:(本文只给出第二种写法)


#include <queue>#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define INF 0x3f3f3f3f#define FIN freopen("in.txt","r",stdin)#define fuck(x) cout<<'['<<x<<']'<<endlusing namespace std;typedef pair<int,int>pii;typedef long long LL;const int MX = 1000 + 10;const int maxn = 1e5 + 10;struct edge{    int v,t;    int nxt;}E[maxn<<1];int head[MX],tot;void init(){    memset(head,-1,sizeof(head));    tot = 0;}void add(int u,int v,int t){    E[tot].v = v;    E[tot].t = t;    E[tot].nxt = head[u];    head[u] = tot++;}int dis[MX],vis[MX];void spfa(int s){    memset(dis,0x3f,sizeof(dis));    memset(vis,0,sizeof(vis));    queue<int>q;    q.push(s);    dis[s] = 0;    while(!q.empty()){        int u = q.front();q.pop();vis[u] = 0;        for(int i = head[u];~i;i = E[i].nxt){            int v = E[i].v;             if(dis[v] > dis[u] + E[i].t){                dis[v] = dis[u] + E[i].t;                if(!vis[v]){                    vis[v] = 1;                    q.push(v);                }             }        }    }}int dis1[MX];void spfa1(int s){    memset(dis1,0x3f,sizeof(dis1));    memset(vis,0,sizeof(vis));    queue<int>q;    q.push(s);    dis1[s] = 0;    while(!q.empty()){        int u = q.front();q.pop();vis[u] = 0;        for(int i = head[u];~i;i = E[i].nxt){            int v = E[i].v;             if(dis1[v] > dis1[u] + E[i].t){                dis1[v] = dis1[u] + E[i].t;                if(!vis[v]){                    vis[v] = 1;                    q.push(v);                }             }        }    }}int n,m,x;int u[maxn],v[maxn],t[maxn];int main(){    //FIN;    while(~scanf("%d%d%d",&n,&m,&x)){        init();        for(int i = 0;i < m;i++){            scanf("%d%d%d",&u[i],&v[i],&t[i]);            add(u[i],v[i],t[i]);//第一次正向连边,spfa求得从X点到其它N-1个点的最短路;        }        spfa(x);        init();//删掉原来所连的边;        for(int i = 0;i < m;i++){            add(v[i],u[i],t[i]);//反向连边,spfa求得从其它N-1个点到X点的最短路;        }        spfa1(x);        int ans = 0;        for(int i = 1;i <= n;i++)            ans = max(ans,dis[i]+dis1[i]);//将两个方向的最短路径相加;        printf("%d\n",ans);    }    return 0;}


原创粉丝点击