POJ 3268 Silver Cow Party (最短路)

时间:2023-02-14 08:58:39

【题目链接】
http://poj.org/problem?id=3268

题目意思

有n只牛,编号从1到n,现在k号家开party,所以牛都会去,当这些牛非常懒,他们想尽可能走短的路(去时加回来),现在路是有向路,问路程最远的一只牛的路程

解题思路

每只牛的路程都可以分成去时和回时。可以用spfa或迪杰斯特拉单源点循环跑,找最大的。弗洛伊德会超时。上面这虽然会过但是耗时大,只要把有向边反过来建立反向图这样跑两遍就够了(看了大神vector用法真的6)。

代码部分


#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <string>
#include <map>
using namespace std;
#define LL long long
//#define inf 0x3f3f3f3
const int N = 1005;
const int inf = 999999;
int dis[N];   ///存储最短路 
int vis[N];  ///记录是否在队列 
int t,k,n;
struct node
{
    int v,w;
}s;
vector<node>m[N];
void spfa(int s)
{
    memset(vis,0,sizeof(vis));
    memset(dis,inf,sizeof(dis)); 
    queue<int>q;
    q.push(s);
    vis[s] = 1;
    dis[s] = 0;
    while (!q.empty())
    {
        int t = q.front();
        q.pop();
        for (int i = 0; i < m[t].size();i++)
        {
            if (dis[m[t][i].v] > dis[t]+m[t][i].w)  ///松弛 
            {
                dis[m[t][i].v] = dis[t]+m[t][i].w;
                if (!vis[m[t][i].v])   ///判断是否在队列 
                {
                    q.push(m[t][i].v);
                    vis[m[t][i].v] = 1;
                }
            }
        }
        vis[t] = 0;
    }
}
int main()
{
    int Max = -1;
    scanf("%d %d %d",&n,&t,&k);
    for(int i =0; i < t;i++)
    {
        int v,u,w;
        scanf("%d %d %d",&u,&v,&w);
        s.v = v;
        s.w = w;
        m[u].push_back(s);
    }
    for (int i = 1; i <= n; i++)
    {
        int s=0;
        spfa(i);
        s += dis[k];
        spfa(k);
        s += dis[i];
        if (Max < s)
            Max = s;
    }
    printf("%d\n",Max);
    return 0;
} 

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <string>
#include <map>
using namespace std;
#define LL long long
//#define inf 0x3f3f3f3
const int N = 1005;
const int inf = 999999;
int dis[N];   ///存储正向最短路 
int fdis[N];  ///存储反向最短路 
int vis[N];  ///记录是否在队列 
int t,k,n;
struct node
{
    int v,w;
}s;
vector<vector<node> >m(N); ///正向图 
vector<vector<node> >fm(N);  ///反向图 
void spfa(int s)
{
    memset(vis,0,sizeof(vis));
    memset(dis,inf,sizeof(dis)); 
    queue<int>q;
    q.push(s);
    vis[s] = 1;
    dis[s] = 0;
    while (!q.empty())
    {
        int t = q.front();
        q.pop();
        for (int i = 0; i < m[t].size();i++)
        {
            if (dis[m[t][i].v] > dis[t]+m[t][i].w)  ///松弛 
            {
                dis[m[t][i].v] = dis[t]+m[t][i].w;
                if (!vis[m[t][i].v])   ///判断是否在队列 
                {
                    q.push(m[t][i].v);
                    vis[m[t][i].v] = 1;
                }
            }
        }
        vis[t] = 0;
    }
}
int main()
{
    int Max = -1;
    scanf("%d %d %d",&n,&t,&k);
    for(int i =0; i < t;i++)
    {
        int v,u,w;
        scanf("%d %d %d",&u,&v,&w);
        s.v = v;
        s.w = w;
        m[u].push_back(s);
        s.v = u;
        fm[v].push_back(s);
    }
    spfa(k);
    memcpy(fdis,dis,sizeof(dis)); 
    m = fm;
    spfa(k);
    for (int i = 1; i <= n; i++)
    {
        Max = max(Max,dis[i]+fdis[i]);
    }
    printf("%d\n",Max);
    return 0;
}