当前位置: 首页 > news >正文

差分约束系列

快乐建模,快乐 spfa。

你需要更快地找负权,你可能需要更厉害的 spfa。SPFA 这一块。

我的题单。

差分约束

1.P5960【模板】差分约束

题意

解决问题形如:

给出一组包含 mmm 个不等式,有 nnn 个未知数的形如:

{xa1−xb1≤y1xa2−xb2≤y2⋯xam−xbm≤ym\begin{cases} x_{a_1}-x_{b_1}\leq y_1 \\x_{a_2}-x_{b_2} \leq y_2 \\ \cdots\\ x_{a_m} - x_{b_m}\leq y_m\end{cases}xa1xb1y1xa2xb2y2xamxbmym

的不等式组,求任意一组满足这个不等式组的解。

1≤n,m≤50001\le n,m\le 50001n,m5000∀i∈[1,n]\forall i\in[1,n]i[1,n] 满足:yi∈[−104,104]y_i\in[-10^4,10^4]yi[104,104]ai≠bia_i\neq b_iai=bi

思路

拿出其中一条式子移项:
xa≤xb+yx_a\le x_b+yxaxb+y

这就很像最短路上松弛一条边的条件。于是想要用图论建模:我们从 j→ij\to iji 连一条权值为 yyy 的有向边。为了使这个有向图连通,我们新建一个 000 号点,从 000 向所有点连 nnn 条权值为 000 的边(xi≤x0+0x_i\le x_0+0xix0+0,对答案没有影响)

我们称这个有向图为差分约束系统。

然后从 000 开始对整个有向图跑一个最短路,0→i0\to i0i 的最短距离是 disidis_idisi{dis}\{dis\}{dis}{x}\{x\}{x} 的一组解。

这个图里面可能会出现环,如果跑出一个负权环 wloop<0w_{loop}<0wloop<0,设环上的某个点 uuu,那么在差分约束系统中 xu≤xu+wloopx_u\le x_u+w_{loop}xuxu+wloop,这显然不成立。因此当这个有向图存在负环,差分约束系统无解。

因为 yyy 的值域有负数而且要找负环,所以只能用 spfa 找负环。具体地,一条边边权为负,会把最短路引向这条边,那么从某个点开始就会沿着负环一直转圈。

我们要知道什么时候要开始转第二圈了。众所周知,n+1n+1n+1 个点的有向图,每个点的最短路的边数 ≤n\le nn(最劣是把所有点经过一次)。因此维护一个 cnticnt_icnti 表示 0→i0\to i0i 最短路经过的边数,当 ∃cnti>n\exist cnt_i>ncnti>n,说明开始转圈,出现负环了。

具体细节见代码:

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=6005,inf=0x3f3f3f3f;
ll n,m;
struct edge
{ll to,next,w;
}e[N<<1];
ll idx,head[N];
void addedge(ll u,ll v,ll w)
{idx++;e[idx].to=v;e[idx].next=head[u];e[idx].w=w;head[u]=idx;
}
queue<ll>q;
bool vis[N];
ll dis[N],cnt[N];//最短路包含边数<=n-1 
bool spfa()//找负环,找带负权最短路
{memset(dis,inf,sizeof(dis));memset(vis,0,sizeof(vis));memset(cnt,0,sizeof(cnt)); dis[0]=0;vis[0]=1;q.push(0);while(!q.empty()){ll u=q.front();q.pop();vis[u]=0;for(int i=head[u];i;i=e[i].next){ll v=e[i].to,w=e[i].w;if(dis[u]+w<dis[v]){dis[v]=dis[u]+w;cnt[v]=cnt[u]+1;if(cnt[v]>n)return 1;//条数>n连接重复点,有个超级源点,出现负环 if(!vis[v]){q.push(v);vis[v]=1;}}}}return 0;
}
int main()
{scanf("%lld%lld",&n,&m);for(int i=1;i<=n;i++)addedge(0,i,0);for(int i=1;i<=m;i++){ll u,v,w;scanf("%lld%lld%lld",&u,&v,&w);addedge(v,u,w);}if(spfa()){puts("NO");return 0;}for(int i=1;i<=n;i++)printf("%lld ",dis[i]);return 0;
}

后面的差分约束题目,都是建模了。

http://www.dtcms.com/a/428845.html

相关文章:

  • 大连网站开发师wordpress 支持vr吗
  • 临沂 网站推广如何推广一个产品
  • 宁波网站建设地方做网站用php还是python
  • 个人网站做推广制作网页填数据
  • 龙虎榜——20250930
  • 《时间回响:蓝环秘境》小说大纲
  • bigquery查询
  • php餐饮美食店网站源码 生成html太原百度关键词推广
  • 国内互联网建站公司排名中铁建设集团有限公司什么级别
  • 蚌埠企业网站建设套餐手机网址进不去怎么设置
  • Android Studio Logcat中 杀死应用
  • 一次由Flowable定时器引发的“401”悬案:深入解析异步线程中的Token传递
  • 龙华哪有做网站设计手加工外包加工网
  • C语言循环与函数详解
  • 昆明做网站那家好建设网站商城
  • seo的网站建设建站基础:wordpress安装教程图解 - 天缘博客
  • centos 7.2 做网站婚礼请柬电子版免费制作app
  • 宜兴网站建设公司qq推广网站
  • 网站建设 设备推广app软件
  • 【动态规划:子数组/子串系列】单词拆分 环绕字符串中唯⼀的子字符串
  • 做网站服务器要什么系统推广怎么推广
  • qq网站登录北京网站优化推广分析
  • CNN的可视化:特征图与卷积核可视化方法(代码实现)
  • 读写RPLMN等APDU log显示为FF FF FF……问题研究
  • CKAD-CN 考试知识点分享(8) 升级与回滚
  • 网站建设公司该如何选择服务称赞的项目管理平台
  • 哪里做网站比较快wordpress主题 视频
  • 网站建设实训总结范文品牌市场营销策略
  • 网站界面设计软件网站备案去哪注销
  • 网页设计感十足的网站移动开发软件