这居然是个紫题???原谅我觉得这题是模板。。。
这个这个,这题的算法呢其实是一个叫差分约束的东西,也是今天下午我们机房的重点,如果不知道这个差分约束是个啥的人呢,自行百度一下谢谢。。
好吧还是简单介绍一下,简而言之,就是对一堆子不等式进行最短路模型化,然后依照问题用最短(长)路跑一(两)遍,基本上就可以求出答案
那么剩下的东西呢都在代码里了
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 }
嗯呐还有好多篇要写,就这样了