[BZOJ 3436] 小K的农场

[题目链接]

         https://www.lydsy.com/JudgeOnline/problem.php?id=3436

[算法]

        不难发现 , 题目中的约束条件都可以写成

        1. Da - Db >= c

        2. Da - Db <= c

        3. Da = Db

        考虑使用差分约束系统

        第一种约束条件 :将b向a连一条权值为c的有向边

        第二种约束条件 :将a向b连一条权值为-c的有向边

        第三种约束条件 :   将a向b连一条权值为0的有向边 , 将b向a连一条权值为0的有向边

        然后 , 我们只需判断该图中是否存在正环 , SPFA判定即可 , 注意使用SPFA的DFS形式

        时间复杂度 : O(N ^ 2)

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
const int inf = 2e9;

struct edge
{
        int to , w , nxt;
} e[MAXN << 1];

int tot , n , m;
bool inq[MAXN];
int dist[MAXN] , head[MAXN];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
inline void addedge(int u , int v , int w)
{
        ++tot;
        e[tot] = (edge){v , w , head[u]};
        head[u] = tot;
}
inline bool spfa(int u)
{
        inq[u] = true;
        for (int i = head[u]; i; i = e[i].nxt)
        {
                int v = e[i].to , w = e[i].w;
                if (dist[u] + w > dist[v])
                {
                        dist[v] = dist[u] + w;
                        if (inq[v]) return true;
                        if (spfa(v)) return true;
                }
        }
        inq[u] = false;
        return false;
} 

int main()
{
        
        read(n); read(m);
        for (int i = 1; i <= m; i++)
        {
                int type;
                read(type);
                if (type == 1)
                {
                        int a , b , c;
                        read(a); read(b); read(c);
                        // d[a] - d[b] >= c
                        addedge(b , a , c);        
                }    else if (type == 2)
                {
                        int a , b , c;
                        read(a); read(b); read(c);
                        // d[a] - d[b] <= c 
                        addedge(a , b , -c);
                } else
                {
                        int a , b;
                        read(a); read(b);
                        // d[a] - d[b] >= 0 , d[b] - d[a] >= 0
                        addedge(b , a , 0);
                        addedge(a , b , 0);
                }
        }
        for (int i = 1; i <= n; i++)
        {
                dist[i] = -inf;
                addedge(0 , i , 0);
        }
        if (!spfa(0)) printf("Yes\n");
        else printf("No\n");
        
        return 0;
    
}

 

        

posted @ 2018-11-08 22:26  evenbao  阅读(182)  评论(0编辑  收藏  举报