zoukankan      html  css  js  c++  java
  • P4878 [USACO05DEC] 布局

    题面lalala

    这居然是个紫题???原谅我觉得这题是模板。。。

    这个这个,这题的算法呢其实是一个叫差分约束的东西,也是今天下午我们机房的重点,如果不知道这个差分约束是个啥的人呢,自行百度一下谢谢。。

    好吧还是简单介绍一下,简而言之,就是对一堆子不等式进行最短路模型化,然后依照问题用最短(长)路跑一(两)遍,基本上就可以求出答案

    那么剩下的东西呢都在代码里了

     1 // luogu-judger-enable-o2
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 using namespace std;
     9 
    10 int n,l,d,tot;
    11 bool ok;
    12 int dis[100005],c[100005],head[100005],next[100005],w[100005],to[100005];
    13 bool vis[100005];
    14 queue < int > q;
    15 
    16 void add(int v,int u,int p){//链式前向星不用多介绍了吧(这玩意要是不会的真的建议理解一下,平时做题复制粘贴虽然可以,但考场不行啊)
    17     next[++tot]=head[v];
    18     to[tot]=u;
    19     w[tot]=p;
    20     head[v]=tot;
    21 }
    22 
    23 void spfa(int s){//由于可能有环及负权边,故用spfa求解
    24     memset(dis,0x3f,sizeof(dis));
    25     dis[s]=0;
    26     memset(c,0,sizeof(c));
    27     memset(vis,0,sizeof(vis));
    28     while(!q.empty()){q.pop();}
    29     q.push(s);
    30     vis[s]=1;
    31     ok=1;
    32     while(!q.empty()){
    33         int x;
    34         x=q.front();
    35         q.pop(); 
    36         vis[x]=0;
    37         for(int k=head[x];k;k=next[k]){
    38             int y=to[k];
    39             if(dis[x]+w[k]<dis[y]){
    40                 dis[y]=dis[x]+w[k];
    41                 if(!vis[y]){
    42                     vis[y]=1;
    43                     c[y]++;
    44                     q.push(y);
    45                 }
    46                 if(c[y]>n){//处理负环的情况
    47                     ok=0;
    48                     return;
    49                 }
    50             }
    51         }
    52     }
    53     return;
    54 }
    55 
    56 int main(){
    57     scanf("%d%d%d",&n,&l,&d);
    58     for(int i=1;i<=n;i++){//这段赋值可以对建图进行预处理,进而处理图非连通的情况
    59         add(0,i,0);
    60     }
    61     for(int i=1;i<=l;i++){//这个读入和下一个读入就是差分约束的核心,简而言之,就是小于等于时建一条a指向b权值为c的边(换行嘤嘤嘤)
    62         int a,b,c;//大于等于时建一条b指向a权值为-c的边
    63         scanf("%d%d%d",&a,&b,&c);
    64         add(a,b,c);
    65     }
    66     for(int i=1;i<=d;i++){
    67         int a,b,c;
    68         scanf("%d%d%d",&a,&b,&c);
    69         add(b,a,-c);
    70     }
    71     spfa(0);
    72     if(!ok){//负环
    73         printf("-1
    ");
    74         return 0;
    75     }
    76     spfa(1);
    77     if(!ok){//负环
    78         printf("-1
    ");
    79     }
    80     else if(dis[n]==0x3f3f3f3f){//不连通
    81         printf("-2
    ");
    82     }
    83     else{
    84         printf("%d
    ",dis[n]);//输出
    85     }
    86     return 0;
    87 }

    嗯呐还有好多篇要写,就这样了

  • 相关阅读:
    java集合归纳
    判断回文数
    29:四则运算计算表达式的值
    getOutString 输出弹出字符串
    两个字符串中不同元素的个数
    字符串各个字符ASCII值加5
    23:一个整数的二进制表示中有多少个1
    Java进程间通信
    转 双重检查锁定与延迟初始化
    Key-Value键值存储原理初识(NOSQL)
  • 原文地址:https://www.cnblogs.com/hahaha2124652975/p/11123369.html
Copyright © 2011-2022 走看看