P4878 [USACO05DEC]Layout G

    科技2026-09-27  17

    文章目录

    R e s u l t Result Result H y p e r l i n k Hyperlink Hyperlink D e s c r i p t i o n Description Description S o l u t i o n Solution Solution C o d e Code Code

    R e s u l t Result Result


    H y p e r l i n k Hyperlink Hyperlink

    https://www.luogu.com.cn/problem/P4878


    D e s c r i p t i o n Description Description

    有 n n n个未知数,给定 m 1 + m 2 m1+m2 m1+m2组限制条件,前 m 1 m1 m1个条件要求满足 a i − a j ≤ D a_i-a_j\leq D ai​−aj​≤D,后 m 2 m2 m2个条件要求满足 a i − a j ≥ D a_i-a_j\geq D ai​−aj​≥D 求一组非负整数解,使得 a n − a 1 a_n-a_1 an​−a1​最大 若此数无穷大,输出-2;若有负环,输出-1

    数据范围: n ≤ 1 0 3 , m 1 + m 2 ≤ 2 × 1 0 4 n\leq 10^3,m_1+m_2\leq 2\times 10^4 n≤103,m1​+m2​≤2×104


    S o l u t i o n Solution Solution

    显然是一道负环差分约束 由于我们要求的是上界,所以要用最短路 建边 ( 0 , i , 0 ) (0,i,0) (0,i,0), d i s i ≥ d i s 0 = 0 dis_i\geq dis_0=0 disi​≥dis0​=0即每个数都非负 对于前 m 1 m_1 m1​个限制条件,建边 ( a , b , c ) (a,b,c) (a,b,c),表示 d i s b ≤ d i s a + c dis_b\leq dis_a+c disb​≤disa​+c即 d i s b − d i s a ≤ c dis_b-dis_a\leq c disb​−disa​≤c 对于后 m 2 m_2 m2​个限制条件,建边 ( b , a , − c ) (b,a,-c) (b,a,−c),表示 d i s a ≤ d i s b − c dis_a\leq dis_b-c disa​≤disb​−c即 d i s b ≥ d i s a + c dis_b\geq dis_a+c disb​≥disa​+c

    然后必须先从 0 0 0开始跑一遍,因为图不一定是联通的


    C o d e Code Code

    #include<queue> #include<cctype> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std;int n,m1,m2,dis[5010],tot,l[5010],in[5010],a,b,c; bool vis[5010]; struct node{int next,to,w;}e[40010]; inline void add(int u,int v,int w){e[++tot]=(node){l[u],v,w};l[u]=tot;return;} queue<int>q; inline LL read() { char c;LL d=1,f=0; while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48; while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48; return d*f; } inline bool spfa(int s) { memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(in,0,sizeof(in)); vis[s]=true;dis[s]=0;in[s]=1; q.push(s); while(q.size()) { int u=q.front();q.pop(); for(register int i=l[u];i;i=e[i].next) { int v=e[i].to,w=e[i].w; if(dis[v]>dis[u]+w) { dis[v]=dis[u]+w; if(vis[v]==0) {vis[v]=1;q.push(v);in[v]++;if(in[v]>n+1) return true;} } }vis[u]=false; } return false; } signed main() { n=read();m1=read();m2=read(); for(register int i=n;i;i--) add(0,i,0);//反过来建边能让你代码效率快五倍 for(register int i=1;i<=m1;i++) a=read(),b=read(),c=read(),add(a,b,c); for(register int i=1;i<=m2;i++) a=read(),b=read(),c=read(),add(b,a,-c); if(spfa(0)+spfa(1)>0) puts("-1"); else printf("%d",dis[n]==0x3f3f3f3f?-2:dis[n]); }
    Processed: 0.013, SQL: 9