P4878 [USACO05DEC] 佈局

題面lalalaios

這竟然是個紫題???原諒我以爲這題是模板。。。算法

這個這個,這題的算法呢實際上是一個叫差分約束的東西,也是今天下午咱們機房的重點,若是不知道這個差分約束是個啥的人呢,自行百度一下謝謝。。spa

好吧仍是簡單介紹一下,簡而言之,就是對一堆子不等式進行最短路模型化,而後依照問題用最短(長)路跑一(兩)遍,基本上就能夠求出答案code

那麼剩下的東西呢都在代碼裏了blog

 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\n");
74         return 0;
75     }
76     spfa(1);
77     if(!ok){//負環
78         printf("-1\n");
79     }
80     else if(dis[n]==0x3f3f3f3f){//不連通
81         printf("-2\n");
82     }
83     else{
84         printf("%d\n",dis[n]);//輸出
85     }
86     return 0;
87 }

嗯吶還有好多篇要寫,就這樣了get

相關文章
相關標籤/搜索