#106-[差分約束]關係運算圖
阿新 • • 發佈:2018-12-11
Description
給出一有向圖,圖中每條邊都被標上了關係運算符‘<’,‘>’,‘=’。現在要給圖中每個頂點標上一個大於等於0,小於等於k的某個整數使所有邊上的符號得到滿足。若存在這樣的k,則求最小的k,若任何k都無法滿足則輸出NO。
例如下表中最小的k為2。
結點1>結點2
結點2>結點3
結點2>結點4
結點3=結點4
如果存在這樣的k,輸出最小的k值;否則輸出‘NO’。
Input
共二行,第一行有二個空格隔開的整數n和m。n表示G的結點個數,m表示G的邊數,其中1<=n<=1000, 0<=m<=10000。全部結點用1到n標出,圖中任何二點之間最多隻有一條邊,且不存在自環。
第二行共有3m個用空格隔開的整數,第3i-2和第3i-1(1<=i<=m)個數表示第i條邊的頂點。第3i個數表示第i條邊上的符號,其值用集合{-1,0,1}中的數表示:-1表示‘<’, 0 表示‘=’, 1表示‘>’。
Output
僅一行,如無解則輸出‘NO’;否則輸出最小的k的值。
Sample Input
4 4
1 2 -1 2 3 0 2 4 -1 3 4 -1
Sample Output
2
差分約束比較模板的一道題,求最小值用SPFA最長路.
#include <iostream> #include <cstring> #include <queue> #define SIZE 1010 #define INF 1e+09 using namespace std; struct edge // 定義一條邊的結構體. { int to, dis; }; vector<edge> graph[SIZE]; queue<int> q; int dis[SIZE], count[SIZE], n; bool inqueue[SIZE]; void spfa(void) // SPFA最長路 { int u, v, w, i, res = 0; for (i = 1; i <= n + 1; ++i) { dis[i] = -INF; } q.push(0); inqueue[0] = true; ++count[0]; while (!q.empty()) { u = q.front(); q.pop(); inqueue[u] = false; for (i = 0; i < graph[u].size(); ++i) { v = graph[u][i].to; w = graph[u][i].dis; if (dis[v] < dis[u] + w) // 這裡條件換一下就可以了 { dis[v] = dis[u] + w; if (!inqueue[v]) { if (++count[v] >= n) // 存在正環 { printf("NO"); return; } q.push(v); inqueue[v] = true; } } } } printf("%d", dis[n+1]); return; } int main(int argc, char** argv) { int m, u, v, w, i; scanf("%d%d", &n, &m); while (m--) { scanf("%d%d%d", &u, &v, &w); switch (w) // 建圖! { case -1: graph[u].push_back({v, 1}); break; case 0: graph[u].push_back({v, 0}); graph[v].push_back({u, 0}); break; case 1: graph[v].push_back({u, 1}); break; } } for (i = 1; i <= n; ++i) { graph[0].push_back({i, 0}); graph[i].push_back({n + 1, 0}); } spfa(); return 0; }