POJ3268 Silver Cow Party(dijkstra,spfa)

55 阅读3分钟

题目:

| Silver Cow Party| Time Limit: 2000MS |   | Memory Limit: 65536K | | ---------------------------- | - | ------------------------ | | Total Submissions: 20481 |   | Accepted: 9382 |DescriptionOne 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?InputLine 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.OutputLine 1: One integer: the maximum of time any one cow must walk.Sample Input4 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 3Sample Output``` 10

| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | - |

\[[Submit](http://poj.org/submit?problem_id=3268)]   \[Go Back]   \[[Status](http://poj.org/problemstatus?problem_id=3268)]   \[[Discuss](http://poj.org/bbs?problem_id=3268)]

思路:

题目先给了n,m,x代表有n个点,m条边(有向图),x代表第x个牛。一群牛要去牛x那里去开会,然后题目求的是那些牛从自己家走到牛x处再返回自己家的最短时间。分析题意,每头牛返回的最短时间很简单就可以算出来,这相当于从目标牛为起点求单源最短路径。但每头牛出发到目标牛的最短时间无法直接算出来,稍微转换一下,发现这个最短时间其实可以通过把所有的边取反向,然后再从目标牛求一次单源最短路径得到。得到这两个最短路径之后,取它们的和的最大者即可。

代码1(dijkstra):

```cpp
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define N 1000+10
#define M 100000+20
#define inf 0x3f3f3f3f
using namespace std;
int map[N][N];
int dis_go[N],vis[N],dis_back[N];//dis_go[i]表示从牛x处到各个牛的最小值,dis_back表示从各个牛到牛x处的最小值
int n,m,x,minn,u;
int dijkstra()
{
    //初始化
    for(int i=1; i<=n; i++)
    {
        vis[i]=0;
        dis_go[i]=map[x][i];
        dis_back[i]=map[i][x];
    }
    //从牛x处到各个牛的距离
    for(int i=1; i<=n; i++)
    {
        minn=inf;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j]&&dis_go[j]<minn)
            {
                minn=dis_go[j];
                u=j;
            }
        }
        vis[u]=1;
        for(int j=1; j<=n; j++)
            if(!vis[j]&&map[u][j]+dis_go[u]<dis_go[j])
                dis_go[j]=map[u][j]+dis_go[u];
    }
    //从各个牛到牛x的距离
    for(int i=1; i<=n; i++)
        vis[i]=0;
    for(int i=1; i<=n; i++)
    {
        minn=inf;
        for(int j=1; j<=n; j++)
            if(!vis[j]&&dis_back[j]<minn)
            {
                u=j;
                minn=dis_back[j];
            }
        vis[u]=1;
        for(int j=1; j<=n; j++)
        {
            if(!vis[j]&&map[j][u]+dis_back[u]<dis_back[j])
                dis_back[j]=map[j][u]+dis_back[u];
        }

    }
    //找出最大值
    minn=-1;
    for(int i=1; i<=n; i++)
    {
        if(dis_go[i]+dis_back[i]>minn)
            minn=dis_go[i]+dis_back[i];
    }
    return minn;
}
int main()
{
    int a,b,c;
    scanf("%d%d%d",&n,&m,&x);
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            if(i==j)
                map[i][j]=0;
            else
                map[i][j]=inf;
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        map[a][b]=c;
    }
    printf("%d\n",dijkstra());

    return 0;
}

代码2(SPFA):

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define N 1000+20
#define M 100000+20
#define inf 0x3f3f3f3f
using namespace std;
int first[M],next[M],vis[M],num,maxx,a,b,c,f1,f2;
int dis[M];
int n,m,x,minn,u;
struct node
{
    int u,v,w;
} G[M];
void add_map(int u,int v,int w)//建立邻接表
{
    G[num].u=u;
    G[num].v=v;
    G[num].w=w;
    next[num]=first[u];
    first[u]=num++;
}
int spfa(int src,int x)
{
    mem(vis,0);
    for(int i=1; i<=n; i++)
        dis[i]=inf;
    dis[src]=0;
    queue<int>q;
    q.push(src);
    vis[src]=1;
    while(!q.empty())
    {
        int k=q.front();
        q.pop();
        vis[k]=0;
        for(int i=first[k]; i!=-1; i=next[i])
        {
            if(dis[k]+G[i].w<dis[G[i].v])
            {
                dis[G[i].v]=dis[k]+G[i].w;
                if(!vis[G[i].v])
                {
                    vis[G[i].v]=1;
                    q.push(G[i].v);
                }
            }
        }
    }
    return dis[x];
}
int main()
{
    mem(first,-1);
    mem(next,-1);
    num=1;
    maxx=0;
    scanf("%d%d%d",&n,&m,&x);
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        add_map(a,b,c);
    }
    for(int i=1; i<=n; i++)
    {
        if(i==x)continue;
        f1=spfa(i,x);
        f2=spfa(x,i);
        if(maxx<(f1+f2))
            maxx=f1+f2;//寻找最短的时间
    }
    printf("%d\n",maxx);
    return 0;
}



\