zoukankan      html  css  js  c++  java
  • 最短路--差分约束

    (a[u]-a[v])的最大值

    已知(a[1]-a[2] <= 5),那么 (a[1]-a[2]) 的最大值就是5
    如果(a[3]-a[2] <= 2)(a[1]-a[3] <= 2),那么(a[1]-a[2]) 的最大值就是4
    翻译一下上面的约束条件,1最多比2大5,3最多比2大2,1最多比3大2
    画个图理解一下

    对于每个不等式 (x[i] - x[j] <= a[k]),对结点 j 和 i 建立一条 j -> i的有向边,边权为a[k]
    (a[u]-a[v])的最大值就是求v到u的最短路

    (a[u]-a[v])的最小值

    已知(a[1]-a[2] >= 5),那么 (a[1]-a[2]) 的最小值就是5
    如果(a[3]-a[2] >= 3)(a[1]-a[3] >= 6),那么(a[1]-a[2]) 的最小值就是9
    翻译一下上面的约束条件,1最少比2大5,3最少比2大3,1最少比3大6
    画个图理解一下

    对于每个不等式 (x[i] - x[j] >= a[k]),对结点 j 和 i 建立一条 j -> i的有向边,边权为a[k]
    (a[u]-a[v])的最大值就是求v到u的最长路

    总结一下

    如果是求最大值的话,统一把差分约束改成<=的形式,然后求最短路,小于号就是最短路
    如果是求最小值的话,统一把差分约束改成>=的形式,然后求最长路,大于号就是最长路
    P5960 【模板】差分约束算法

    code

    #pragma GCC optimize(2)
    #include <bits/stdc++.h>
    using namespace std;
    #define debug(x) cerr << #x << " : " << x << " " << endl
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pii pair<int,int>
    #define gcd __gcd
    const int inf = 0x3f3f3f3f;
    const int maxn = 201110;
    const int M = 1e9+7;
    int n,m,k,ok;
    
    int head[maxn],cost[maxn],to[maxn],Next[maxn],cnt = 2;
    
    void add(int u,int v,int w)
    {
        to[cnt] = v;cost[cnt] = w;Next[cnt] = head[u];head[u] = cnt;cnt++;
    }
    
    int in[maxn];
    bool vis[maxn];
    int dis[maxn];
    
    bool spfa(int u)            //spfa求最短路
    {   
        mem(dis,inf);dis[u] = 0;
        queue<int> q;q.push(u);
        while (!q.empty())
        {
            u = q.front();q.pop();vis[u] = 0;
            for(int i = head[u]; i ; i = Next[i])
            {
                int v = to[i];
                if(dis[v] > dis[u]+cost[i])        //求最长路把这里改成大于就好了
                {   
                    dis[v] = dis[u]+cost[i];
                    if(!vis[v])
                    {
                        vis[v] = 1;
                        q.push(v);
                        in[v]++;
                        if(in[v] == n+1) return false;            //出现负环,如果是求最长路就是出现正换
                    }
                }
            }
        }
        return true;
    }
    
    signed main()
    {
        cin>>n>>m;
        for(int i = 1; i <= n; i++)         //确保联通,构建超级源点
        {
            add(n+1,i,0);
        }
        for(int i = 1,u,v,w; i <= m; i++) 
        {
            cin>>u>>v>>w;
            add(v,u,w);
        }
        if(spfa(n+1))
        {
            for(int i = 1; i <= n; i++) 
            {
                cout<<dis[i]<<' ';
            }
            cout<<endl;
        }
        else puts("NO");
        return 0;
    }
    

    参考博客

    https://www.cnblogs.com/zzz-hhh/p/11200893.html#664675501

  • 相关阅读:
    【乱侃】How do they look them ?
    【softeware】Messy code,some bug of Youdao notebook in EN win7
    【随谈】designing the login page of our project
    【web】Ad in security code, making good use of resource
    SQL数据库内存设置篇
    关系数据库的查询优化策略
    利用SQL未公开的存储过程实现分页
    sql语句总结
    sql中使用cmd命令注销登录用户
    SQLServer 分页存储过程
  • 原文地址:https://www.cnblogs.com/hezongdnf/p/12365638.html
Copyright © 2011-2022 走看看