• bzoj2019 [Usaco2009 Nov]找工作


    Description

    奶牛们没钱了,正在找工作。农夫约翰知道后,希望奶牛们四处转转,碰碰运气。而且他还加了一条要求:一头牛在一个城市最多只能赚D(1 <= D <= 1,000)美元,然后它必须到另一座城市工作。当然,它可以在别处工作一阵后又回来原来的城市再最多赚D美元。而且这样往往返返的次数没有限制。 城市间有P (1 <= P <= 150)条单向路径连接,共有C(2 <= C <= 220)座城市,编号1..C. 贝希当前处在城市S (1 <= S <= C)。路径 i 从城市A_i 到城市B_i (1 <= A_i <= C; 1 <= B_i <= C),在路径上行走不用花任何费用。为了帮助贝希,约翰让它使用他的私人飞机服务。这项服务有F条(1 <= F <= 350)航线,每条航线是从城市J_i飞到另一座城市K_i (1 <=J_i <= C; 1 <= K_i <= C),费用是T_i (1 <= T_i <= 50,000)美元。如果贝希手中如果没有现钱,可以用以后赚的钱来付机票钱。贝希可以选择任何时候,在任何城市退休。如果在工作时间上不作限制,贝希总共可以赚多少钱呢? 如果赚的钱也不会出现限制,就输出-1。

    Input

    第1行: 5个空格分开的整数 D, P, C, F, S

    第2..P+1行: 第 i+1行包含2个空格分开的整数,表示一条从A_i 到 B_i的单向路径

    第P+2..P+F+1行: 第P+i 包含3个空格分开的整数,表示一条从J_i到K_i的单向航线,费用为T_i

    Output

    第1行: 在上述规则下的最多可赚的钱数。

    Sample Input

    100 3 5 2 1
    1 5
    2 3
    1 4
    5 2 150
    2 5 120

    Sample Output

    250

    HINT

    样例说明:贝希可以从城市 1 到 5 再到 2 ,最后到 3, 总共赚 4*100 - 150 = 250 美元。

    显然

    为了拿个省一而开始刷水了。。
    点有权值,边也有权值,所以应该考虑把点上的权值转到边上。
    对于每条无费用边,把权值改成d,对每条有v费用边,权值改成d-v,显然最大路径权值和即是所求,有正环的时候就输出-1
    有正环。。多别扭啊
    所以把边权反过来,这样判负环即可
    最后,因为会经过k个点k-1条边,所以点权要多算一次
    这简直是无脑spfa。。
     
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 int head[100010];
     6 int tot[100010];
     7 int q[100010];
     8 int dis[100010];
     9 bool mrk[100010];
    10 struct edge{int to,next,v;}e[100000];
    11 int d,p,n,f,S,t=0,w=1,cnt;
    12 inline void ins(int u,int v,int w)
    13 {
    14     e[++cnt].to=v;
    15     e[cnt].next=head[u];
    16     e[cnt].v=w;
    17     head[u]=cnt;
    18 }
    19 inline bool spfa()
    20 {
    21     memset(q,0,sizeof(q));
    22     memset(mrk,0,sizeof(mrk));
    23     memset(dis,127/3,sizeof(dis));
    24     dis[S]=-d;q[1]=S;mrk[S]=1;
    25     t=0;w=1;
    26     while (t<w)
    27     {
    28         int now=q[++t];
    29         for(int i=head[now];i;i=e[i].next)
    30           if (dis[e[i].to]>dis[now]+e[i].v)
    31             {
    32                 dis[e[i].to]=dis[now]+e[i].v;
    33                 if (!mrk[e[i].to])
    34                 {
    35                     q[++w]=e[i].to;
    36                     mrk[e[i].to]=1;
    37                     tot[e[i].to]++;
    38                     if (tot[e[i].to]>n)return 1;
    39                 }
    40             }
    41         mrk[now]=0;
    42     }
    43     return 0;
    44 }
    45 int main()
    46 {
    47     scanf("%d%d%d%d%d",&d,&p,&n,&f,&S);
    48     for (int i=1;i<=p;i++)
    49     {
    50         int x,y;scanf("%d%d",&x,&y);
    51         ins(x,y,-d);
    52     }
    53     for(int i=1;i<=f;i++)
    54     {
    55         int x,y,z;scanf("%d%d%d",&x,&y,&z);
    56         ins(x,y,z-d);
    57     }
    58     if (spfa())
    59     {
    60         printf("-1");
    61         return 0;
    62     }
    63     int mx=d;
    64     for (int i=1;i<=n;i++)
    65         if (-dis[i]>mx)mx=-dis[i];
    66     printf("%d
    ",mx);
    67 }
    bzoj2019
    ——by zhber,转载请注明来源
  • 相关阅读:
    Win10安装.NetFamework3.5
    SAN和NAS的区别
    raid10模型比raid01模型的冗余度高
    Linux——查找占用磁盘体积最大的前10个文件
    Nginx——端口负载均衡
    oneinstack——证书更新
    SpringBoot——IDEA使用 Spring Initializer快速创建项目【四】
    Nginx——请求head被过滤
    Linux—— 记录所有登陆用户的历史操作记录
    Nginx——跨域造成的504问题
  • 原文地址:https://www.cnblogs.com/zhber/p/4793103.html
Copyright © 2020-2023  润新知