首页 > 其他分享 >差分约束:求最小->求所有下界的最大->最长路 √

差分约束:求最小->求所有下界的最大->最长路 √

时间:2022-08-31 16:13:43浏览次数:63  
标签:int top scc stk ++ add 差分 下界 最长

最长路 如果有正环就输出无解
a>b 那么b到a连一条长度为1的边
结论:
一个正环一定是某个scc中的 对于某个scc中的所有边 ,只要又一个边的权重是严格>0

因为u+w->b w>0
又u和v 在一个scc中 则v也一定能到v 所以就存在一个正环

那么当没有正环的时候 经过tarjan的图就是top图 x[i]最小
那么就使用top求dp最长路

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 100010, M = 600010;

int n, m;
int h[N], hs[N], e[M], ne[M], w[M], idx;
int dfn[N], low[N], timestamp;
int stk[N], top;
bool in_stk[N];
int id[N], scc_cnt, scc_size[N];
int dist[N];

void add(int h[],int a,int b,int c)
{
    e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx++;
}

void tarjan(int u)
{
    dfn[u] = low[u] = timestamp++;
    stk[++top] = u,in_stk[u] = true;//stk[++top]要和stk[top--]配 而不是stk[top++] stk[0++] = u stk[1++] = t 

    for(int i = h[u];~i;i=ne[i])
    {
        int j = e[i];
        if(!dfn[j])
        {
            tarjan(j);
            low[u] = min(low[u],low[j]);
        }
        else if(in_stk[j]) low[u] = min(low[u],dfn[j]);
    }
    if(dfn[u]==low[u])
    {
        scc_cnt++;
        int y;
        do
        {
            y = stk[top--];//忘了强连通分量都是通过dfs后在一个栈里的
            in_stk[y] = false;//漏了
            id[y] = scc_cnt;
            scc_size[scc_cnt]++;
        }while(y!=u);//漏了
    }
}

int main()
{
    cin >> n >> m;
    memset(h,-1,sizeof h);
    memset(hs,-1,sizeof h);
    // 超级源点 和i有一个1的边
    for(int i = 1;i<=n;i++)add(h,0,i,1);
    while(m--)
    {
        int t,a,b;
        cin >> t >> a >> b;
        if(t==1)add(h,b,a,0),add(h,a,b,0);
        else if(t==2)add(h,a,b,1);
        else if(t==3)add(h,b,a,0);
        else if(t==4)add(h,b,a,1);
        else add(h,a,b,0);
    }
    tarjan(0);
    bool success = true;
    for(int i=0;i<=n;i++)//对于每条边的两个点 如果点在同一个scc中而且编制>0就说明是正环
    {
        for(int j = h[i];~j;j=ne[j])
        {
            int k = e[j];
            int a = id[i],b = id[k];
            // 如果a和b在一个scc里,判断w[a][b]是否>0
            if(a==b)
            {
                if(w[j]>0)
                {
                    success = false;
                    break;
                }
            }
            // 如果不在一个scc里 在新图里加一条边
            else add(hs,a,b,w[j]);
        }
        if(!success) break;
    }
    if(!success) cout << "-1";
    else
    {
        // 有解 求最长路
        for(int i = scc_cnt;i;i--)
        {
            for(int j = hs[i];~j;j=ne[j])
            {
                int k = e[j];
                dist[k] = max(dist[k],dist[i]+w[j]);
            }
        }
        LL res = 0;
        // 结果 = 新图里每个scc的距离 * scc里的点数 = dist[scc] * cnt[scc] 
        for(int i=1;i<=scc_cnt;i++) res+=(LL)dist[i]*scc_size[i];
        cout << res;
    }
    return 0;
}


标签:int,top,scc,stk,++,add,差分,下界,最长
From: https://www.cnblogs.com/liang302/p/16643426.html

相关文章

  • 动态规划之——最长递增子序列
    最长递增子序列(LongestIncreasingSubsequence)是指在给定的一组数字中,按照从左向右顺序,由递增的数字组成的子序列(中间可以有间隔)中,取长度最大的子序列即为最长递增子序列......
  • leetcode 409 Longest Palindrome 最长回文串(简单)
    一、题目大意给定一个包含大写字母和小写字母的字符串s,返回通过这些字母构造成的最长的回文串。在构造过程中,请注意区分大小写。比如"Aa"不能当做一个回文字符......
  • 方差分析、T检验、卡方分析如何区分?
    差异研究的目的在于比较两组数据或多组数据之间的差异,通常包括以下几类分析方法,分别是方差分析、T检验和卡方检验。三个方法的区别其实核心的区别在于:数据类型不一样。......
  • 求一个图的最打的半联通子集=求一个图的最长链方案和个数
    拓扑图最长路等于背包问题求方案数因为要求点不同存在多条边同一情况需要边判重(set)拓扑求方案数#include<iostream>#include<cstring>#include<algorithm>......
  • P4551 最长异或路径
    给定树上\(n\)个点和边权,求两点间所有边权的异或和最大。\(n\leq10^5\)。首先如果假定一个根,那么所有点到根的距离\(dis[i]\)中两两异或得到的就是答案。(\(x,y\)......
  • 动态规划之——最长公共子序列
    先看下最长公共子序列(LongestCommonSubsequence)的问题描述。给定两个字符串,求两者的最长公共子序列的长度。子序列是指从字符串中按特定顺序(从左向右或从右向左,可以有......
  • Gym 101775J Straight Master(差分数组)
    题意:给你n个高度,再给你1n每种高度的数量,已知高度连续的35个能消去,问你所给的情况能否全部消去;例:n=4,给出序列1221表示高度1的1个,高度2的2个,高度3的2个,高度4的1个。那......
  • 2022牛客多校 第9场 C Global Positioning System(讨论+lca+树上差分)
    传送门若干条路径生成了一个无向连通图,只有所有简单回路对应的向量为\(0\)向量时合法。需要改变的边是满足这个边是所有不为\(0\)回路的交且不属于所有为\(0\)的回路。......
  • 最长上升子序列【模板】
     P1439【模板】最长公共子序列-洛谷|计算机科学教育新生态(luogu.com.cn)n^2的最长上升子序列解法#include<iostream>usingnamespacestd;intdp[1001][100......
  • 动态规划——leetcode5、最长回文子串
    1、题目描述:2、解题方法:动态规划动态规划解题步骤:1、确定状态最后一步:如果s[i,...,j]是回文子串,那么需要满足两个条件①s[i......