bzoj 1731 Layout 排队布局 —— 差分约束

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1731

差分约束;

ML: dis[y] - dis[x] <= k,即 x 向 y 连边权为 k 的边;

MD: dis[y] - dis[x] >= k,即 y 向 x 连边权为 -k 的边;

有负环说明要 <= 的 k 无限小,所以无解,输出 -1;

走不到说明 1 与 n 之间无限制关系,所以 dis[n] 可以无限大,输出 -2;

还要注意隐藏条件是编号小的在编号大的前面,所以还有 dis[x-1] <= dis[x];

注意 spfa 判负环那里是松弛次数不超过 n 而不是入队次数(入队次数也可以?总之WA了...)。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
int const xn=1005,xm=20005+xn;//!!!
int n,ml,md,hd[xn],ct,to[xm],nxt[xm],w[xm],cnt[xn];
ll dis[xn];
bool vis[xn];
queue<int>q;
void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
int rd()
{
    int ret=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
    while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    return f?ret:-ret;
}
ll spfa()
{
    memset(dis,0x3f,sizeof dis); ll inf=dis[1];//ll
    dis[1]=0; q.push(1); cnt[1]=1; vis[1]=1; 
    while(q.size())
    {
        int x=q.front(); q.pop(); vis[x]=0;
        for(int i=hd[x],u;i;i=nxt[i])
            if(dis[u=to[i]]>dis[x]+w[i])
            {
                dis[u]=dis[x]+w[i];
                if(!vis[u])vis[u]=1,q.push(u);
                cnt[u]++;//不一定入队
                if(cnt[u]>=n)return -1;
            }
    }
    if(dis[n]==inf)return -2;
    return dis[n];
}
int main()
{
    n=rd(); ml=rd(); md=rd();
    for(int i=1,x,y,z;i<=ml;i++)
    {
        x=rd(); y=rd(); z=rd();
        add(x,y,z);
    }
    for(int i=1,x,y,z;i<=md;i++)
    {
        x=rd(); y=rd(); z=rd();
        add(y,x,-z);
    }
    for(int x=2;x<=n;x++)add(x,x-1,0);
    printf("%lld\n",spfa());
    return 0;
}

 

转载于:https://www.cnblogs.com/Zinn/p/9705203.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值