zoukankan      html  css  js  c++  java
  • bzoj2330

    差分约束系统

    1.du=dv 2.du+1<=dv 3.du>=dv 4.du>=dv+1 5.du<=dv

    事实上,这道题希望总和最小,于是我们由小于号的左边连向右边,边权为常数项,跑最长路就可以了。

    ①:对于差分不等式,a - b <= c ,建一条 b 到 a 的权值为 c 的边,求的是最短路,得到的是最大值 
    ②:对于不等式 a - b >= c ,建一条 b 到 a 的权值为 c 的边,求的是最长路,得到的是最小值 
    ③:存在负环的话是无解 
    ④:求不出最短路(dist[ ]没有得到更新)的话是任意解 

    这是差分约束的通常解法

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    struct edge {
        int nxt, to, w;
    } e[N << 2];
    int n, k, cnt = 1;
    int vis[N], d[N], head[N], cir[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()
    {
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= k; ++i)
        {
            int u, v, opt;
            scanf("%d%d%d", &opt, &u, &v);
            if(opt == 1)
            {
                link(u, v, 0);
                link(v, u, 0);
            }
            if(opt == 2) 
            {
                if(u == v)
                {
                    puts("-1");
                    return 0;
                }
                link(u, v, 1);
            }
            if(opt == 3) link(v, u, 0);
            if(opt == 4) 
            {
                if(u == v)
                {
                    puts("-1");
                    return 0;
                }
                link(v, u, 1);
            }
            if(opt == 5) link(u, v, 0);
        }
        queue<int> q;
        memset(d, 0x3f3f, sizeof(d));
        for(int i = n; i; --i) link(0, i, 1);
        d[0] = 0;
        q.push(0);
        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)
                {
                    ++cir[e[i].to];
                    if(cir[e[i].to] == n) 
                    {
                        puts("-1");
                        return 0;
                    }
                    vis[e[i].to] = 1;
                    q.push(e[i].to);
                }        
            }
        }
        long long ans = 0;
        for(int i = 1; i <= n; ++i) ans += d[i];
        printf("%lld
    ", ans);
        return 0;
    } 
    View Code
  • 相关阅读:
    无题
    赌对了
    赌:
    这次是真的再见了,oi退役回忆录
    线段树(lazy标记)
    《挑战》2.1 POJ POJ 1979 Red and Black (简单的DFS)
    《挑战》2.1 POJ 2386 Lake Counting (简单的dfs)
    TC安装全系列教程
    ProblemC 剪花布条(KMP基础)
    多校+CF简单题
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7427986.html
Copyright © 2011-2022 走看看