poj3169 差分約束+spfa
阿新 • • 發佈:2019-01-13
題目連結在這裡
題目大意是有N頭牛,有的牛喜歡相互捱得近一點,有的想相互離得遠一點。輸入的第一行給出三個數N, ML, MD,分別代表N頭牛,有ML條資料是離得近一點,MD條資料是離得遠一點。接下來有ML + MD條資料,每條資料有a b c三個數,代表牛a和牛b離得不超過(或者最少是)c。問第一頭牛和第二頭牛最遠能隔多少。
這是一個差分約束題目,我們分析一下。
假設a是編號比較小的牛,即a < b。那麼如果兩條牛想捱得近一點的話,應該滿足b - a <= c,即有一條點a指向點b且權值為c的邊。如果是兩條牛想捱得比較遠一點的話,就要滿足b - a >= c,換算一下就是a - b <= -c,即有一條b指向a且權值為-c的邊。然後構建邊,用spfa尋找最短路就行了。
程式碼如下:
#include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #include <queue> using namespace std; const int MaxN = 1010; const int MaxM = 20010; const int INF = 0x3f3f3f3f; int n, ml, md; int cnt[MaxN], dis[MaxN]; struct Edge{ int v, w, nxt; }edge[MaxM]; int head[MaxN], tol; void addEdge(int u, int v, int c){ edge[tol].v = v; edge[tol].w = c; edge[tol].nxt = head[u]; head[u] = tol++; } int spfa(int st){ memset(dis, INF, sizeof(dis)); memset(cnt, 0, sizeof(cnt)); dis[st] = 0; cnt[st] = 1; priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que; que.push(make_pair(0, st)); while(!que.empty()){ pair<int, int> p = que.top(); que.pop(); if(p.first != dis[p.second]) continue; for(int i = head[p.second]; i != -1; i = edge[i].nxt){ int v = edge[i].v; if(dis[v] > dis[p.second] + edge[i].w){ dis[v] = dis[p.second] + edge[i].w; que.push(make_pair(dis[v], v)); if(++cnt[v] > n) return 0; } } } return 1; } int main(){ while(~scanf("%d %d %d", &n, &ml, &md)){ memset(head, -1, sizeof(head)); tol = 0; int a, b, c; while(ml--){ scanf("%d %d %d", &a, &b, &c); if(a > b) swap(a, b); addEdge(a, b, c); //滿足b - a <= c, 是一個由a指向b的邊 } while(md--){ scanf("%d %d %d", &a, &b, &c); if(a < b) swap(a, b); addEdge(a, b, -c); //滿足大 - 小 >= c --> 小 - 大 <= -c, 大邊指向小邊 } if(!spfa(1)) printf("-1\n"); else{ if(dis[n] == INF) printf("-2\n"); else printf("%d\n", dis[n]); } } return 0; }