bzoj1202

差分约束系统

我们把前缀和看成一个点,每个点之间的关系就是sum[i]-sum[j-1]=?,然后我们拆成sum[i]-sum[j-1]>=?和sum[j-1]-sum[i]>=-?,大于等于号是跑最长路,边从b连向a,边权是符号后面的常数项,然后跑最长路就行了,我们可以用dfs版spfa跑

#include<bits/stdc++.h>
using namespace std;
const int N = 2010;
struct edge {
    int nxt, to, w;
} e[N << 1];
int n, m, cnt = 1;
int head[N], d[N], vis[N], in[N];
void link(int u, int v, int w)
{
    e[++cnt].nxt = head[u];
    head[u] = cnt;
    e[cnt].to = v;
    e[cnt].w = w;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        memset(head, 0, sizeof(head));
        cnt = 1;
        for(int i = 1; i <= m; ++i)
        {
            int l, r, v;
            scanf("%d%d%d", &l, &r, &v);
            link(l - 1, r, v);
            link(r, l - 1, -v);
        }
        queue<int> q;
        for(int i = 0; i <= n; ++i) q.push(i), in[i] = d[i] = 0, vis[i] = 1;
        bool flag = true;
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for(int i = head[u]; i; i = e[i].nxt) if(d[e[i].to] < d[u] + e[i].w)
            {
                d[e[i].to] = d[u] + e[i].w;
                if(vis[e[i].to] == 0)
                {
                    ++in[e[i].to];
                    if(in[e[i].to] == n)
                    {
                        puts("false");
                        flag = false;
                        break;
                    }
                    vis[e[i].to] = 1;
                    q.push(e[i].to);
                }
            }
            if(!flag) break;
        }
        if(flag) puts("true");
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/19992147orz/p/7462659.html