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 }

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

原文地址:https://www.cnblogs.com/hahaha2124652975/p/11123369.html