題面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