zoukankan      html  css  js  c++  java
  • USACO 2007 February Contest, Silver Problem 3. Silver Cow Party SPFA

    题目:

    问题描述:

    John Farmer的牧场有n(1n1,000)头奶牛,分别住在对应编号1..n的牧场。将参加编号X(1Xn) 的奶牛牧场聚会。总共m(1m100,000)条单向道路连接成对的牧场;第i条道路需要Ti(1Ti100)单位时间。

    每头奶牛都必须走到聚会,聚会结束后再返回到自己的牧场。每头奶牛都要选择一条最短路线。因为是单向道路,奶牛的回程路线可能与来时不同,所有奶牛都选择最短路线往返,请找出奶牛中花费最长的时间?

    入格式:

    第1行: 三个整数n(1n1,000) 头奶牛,m(1m50,000)条单向道路,将参加编号X(1Xn)奶牛牧场的聚会。

    第2…m+1行: 第i+1行三个整数描述第i条单向道路,Ai,Bi表示一条道路从Ai到Bi,需要Ti(1Ti100)单位时间。

    输出格式:

    仅1行1个整数,表示奶牛中花费最长的时间。

    输入输出样例:

    sparty.in

    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

    sparty.out

    10

    输入输出解释:

    总共有4头牛;8条单向道路,在编号2的牧场聚会。奶牛1往返4+1=5;奶牛2往返0;奶牛3往返2+4+1+2=9;奶牛4往返3+1+2+4=10时间最长,输出10。

    程序:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int n,m,p,i,j,t[50005],k[50005],s[50005],Head[1005],f1[1005],f[1005];
     6 bool flag[1005];
     7 struct edge
     8 {
     9     int Next,Weight,Aim;
    10 }Edge[50005];
    11 
    12 void add(int u,int v,int w,int x)
    13 {
    14     Edge[x].Next=Head[u];
    15     Head[u]=x;
    16     Edge[x].Weight=w;
    17     Edge[x].Aim=v;
    18 }
    19 
    20 void SPFA()
    21 {
    22     int i;
    23     queue<int> Q;
    24     memset(flag,0,sizeof(flag));
    25     memset(f,0x3f3f3f3f,sizeof(f));
    26     flag[p]=1;f[p]=0;
    27     Q.push(p);
    28     while (!Q.empty())
    29     {
    30         int t=Q.front();
    31         Q.pop();
    32         flag[t]=0;
    33         for (i=Head[t];i;i=Edge[i].Next)
    34             if (f[Edge[i].Aim]>Edge[i].Weight+f[t])
    35             {
    36                 f[Edge[i].Aim]=Edge[i].Weight+f[t];
    37                 if (flag[Edge[i].Aim]==0)
    38                 {
    39                     Q.push(Edge[i].Aim);
    40                     flag[Edge[i].Aim]=1;
    41                 }
    42             }
    43     }
    44 }
    45 
    46 int main()
    47 {
    48     freopen("sparty.in","r",stdin);
    49     freopen("sparty.out","w",stdout);
    50     cin>>n>>m>>p;
    51     for (i=1;i<=m;i++)
    52         cin>>t[i]>>k[i]>>s[i];
    53     for (i=1;i<=m;i++)
    54         add(t[i],k[i],s[i],i);
    55     SPFA();
    56     for (i=1;i<=n;i++)
    57         f1[i]=f[i];
    58     memset(Head,0,sizeof(Head));
    59     for (i=1;i<=m;i++)
    60         add(k[i],t[i],s[i],i);
    61     SPFA();
    62     int ans=0;
    63     for (i=1;i<=n;i++)
    64         ans=max(ans,f[i]+f1[i]);
    65     cout<<ans<<endl;
    66     return 0;
    67 }

    分析:

    这道题目显然就是一个单源最短路。先按照原图从聚会的地方往牧场的方向跑SPFA,然后反过来从牧场的方向往聚会的地方跑SPFA。

    简单分析一下SPFA的原理。

    简单来说SPFA的形式和广度优先搜索(BFS)有些类似。首先建立一个队列Q,队列中存储的是所有待处理的点。在队列非空时开始循环,弹出队首元素存入t,然后循环所有以为开始节点的边。如果当前循环的边的终点的最短路长度可以更新,那么就更新它(废话)。这个点的值被更新过以后,意味着这条边的终点也成为了一个需要处理的点。如果它现在不在队列中,把它加入队列,作为一个需要处理的点。SPFA:

     procedure Shortest-Path-Faster-Algorithm(G, s)
      1    for each vertex v ≠ s in V(G)
      2        d(v) := ∞
      3    d(s) := 0
      4    offer s into Q
      5    while Q is not empty
      6        u := poll Q
      7        for each edge (u, v) in E(G)
      8            if d(u) + w(u, v) < d(v) then
      9                d(v) := d(u) + w(u, v)
     10                if v is not in Q then
     11                    offer v into Q
  • 相关阅读:
    python使用matplotlib:subplot绘制多个子图 不规则画图
    Python_matplotlib画图时图例说明(legend)放到图像外侧
    python ndarray与pandas series相互转换,ndarray与dataframe相互转换
    用Python实现excel 14个常用操作
    Python中保留两位小数的几种方法
    画图显示中文
    python命名规范
    Alpha阶段小结
    敏捷冲刺每日报告——Day5
    敏捷冲刺每日报告——Day4
  • 原文地址:https://www.cnblogs.com/OIerPrime/p/8094724.html
Copyright © 2011-2022 走看看