1. 程式人生 > >bzoj3436: 小K的農場(差分約束系統)

bzoj3436: 小K的農場(差分約束系統)

原題連結

題目描述:小K是個特麼喜歡玩MC的孩紙。。。
小K在MC裡面建立很多很多的農場,總共n個,以至於他自己都忘記了每個農場中種植作物的具體數量了,他只記得
一些含糊的資訊(共m個),以下列三種形式描述:農場a比農場b至少多種植了c個單位的作物,農場a比農場b至多
多種植了c個單位的作物,農場a與農場b種植的作物數一樣多。但是,由於小K的記憶有些偏差,所以他想要知道存
不存在一種情況,使得農場的種植作物數量與他記憶中的所有資訊吻合。

輸入格式:第一行包括兩個整數n和m,分別表示農場數目和小K記憶中的資訊的數目接下來m行:如果每行的第一個數是1,接下來有三個整數a,b,c,表示農場a比農場b至少多種植了c個單位的作物如果每行第一個數是2,接下來有三個整數a,b,c,表示農場a比農場b至多多種植了c個單位的作物如果每行第一個數是3,接下來有兩個整數a,b,表示農場a種植的數量與b一樣。1<=n,m,a,b,c<=10000

輸出格式:如果存在某種情況與小K的記憶吻合,輸出”Yes”,否則輸出”No”。

輸入樣例
3 3
3 1 2
1 1 3 1
2 2 3 2

輸出樣例
Yes

解析:又是一道差分約束的題。。。
   對於\(a-b≥c\),連一條w[b,a]=c的邊。
   對於\(a-b≤c\),連一條w[a,b]=-c的邊。
   對於\(a=b\),連兩條w[a,b]=0,w[b,a]=0的邊。
   最後跑一遍最長路即可。
   注意要用dfs代替spfa,不然會超時。

#include<cstdio>
using namespace std;

const int maxn = 10005;
const int maxm = 30005;
int n, m, vis[maxn], dis[maxn];
int nxt[maxm], hed[maxm], to[maxm], val[maxm], cnt;

int read(void) {
    char c; while (c = getchar(), c < '0' || c >'9'); int x = c - '0';
    while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; return x;
}

void add(int x, int y, int v) {
    nxt[++ cnt] = hed[x]; hed[x] = cnt; to[cnt] = y; val[cnt] = v;
}

int dfs(int u) {
    vis[u] = 1; 
      for (int i = hed[u]; i ; i = nxt[i]) {
        int v = to[i];
          if (dis[v] < dis[u] + val[i]) {
              dis[v] = dis[u] + val[i];
              if (vis[v] || !dfs(v)) return 0; 
            }
      }
    vis[u] = 0;
    return 1;
}

int main() {
    n = read(); m = read();
      for (int i = 1; i <= m; ++ i) {
        int opt = read();
          if (opt == 1) {
              int x = read(), y = read(), v = read();
              add(y, x, v);
            }
          else if (opt == 2) {
            int x = read(), y = read(), v = read();
            add(x, y, -v);
          }
          else {
            int x = read(), y = read();
            add(x, y, 0); add(y, x, 0);
          }
      }
      for (int i = 1; i <= n; ++ i) add(0, i, 0);
      for (int i = 1; i <= n; ++ i) dis[i] = -2e9;
      if (dfs(0)) printf("Yes"); else printf("No");
    return 0;
}