题目链接:点击查看

题目大意:给出一张 n 个点 m 条边的无向图,每个点代表一个人,每个人都有一个权值 a[ i ],每条边代表朋友关系,规定如果两个朋友之间,权值较小的人会嫉妒权值较大的人。每个朋友关系之间都会产生一个嫉妒关系,更具体的来说,对于 ( u , v ) 来说,要么 a[ u ] = a[ v ] + 1,要么 a[ v ] = a[ u ] + 1,输入时已经确定了某些边的嫉妒关系,现在问如何构造,可以使得 max( a[ i ] ) - min( a[ i ] ) 最大

题目分析:吐槽一下,有的题解只讲怎么建边,而不讲为什么要这样建边,难道图论最难想的部分不就是建图部分吗?能看到这个题目还需要去学学Floyd怎么写,学学Floyd怎么判负环吗?

回到正题,首先因为每条边都会产生 +1 或 -1 的关系,所以将 a[ i ] 按照奇偶分开,不难看出原图是一张二分图,所以题目有解的一个必要条件就是原图是一张二分图

然后考虑差分约束系统的模型:(百度百科)

如果一个系统由n个变量和m个约束条件组成,形成m个形如ai-aj≤k的不等式(i,j∈[1,n],k为常数),则称其为差分约束系统(system of difference constraints)。亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法。

此处的变量对应着题目中的 n 个人,约束条件对应着 m 个朋友关系,首先需要列出不等式组,形式如此:x + y <= k ,分两种情况讨论:

  1. | a[ u ] - a[ v ] | = 1:拆去绝对值,得到两个等式:

    1. a[ u ] - a[ v ] = 1,转换成不等式:

      1. a[ u ] - a[ v ] <= 1
      2. a[ u ] - a[ v ] >= 1
      3. 统一形式:a[ u ] - a[ v ] <= 1,a[ v ] - a[ u ] <= -1
    2. a[ v ] - a[ u ] = 1,转换成不等式:
      1. a[ v ] - a[ u ] <= 1
      2. a[ v ] - a[ u ] >= 1
      3. 统一形式:a[ v ] - a[ u ] <= 1,a[ u ] - a[ v ] <= -1
  2. a[ v ] - a[ u ] = 1,转化成不等式:
    1. a[ v ] - a[ u ] <= 1
    2. a[ v ] - a[ u ] >= 1
    3. 统一形式:a[ v ] - a[ u ] <= 1,a[ u ] - a[ v ] <= -1

对于所有 x - y <= k 的边,在建图时建立一条 y -> x 权值为 k 的边即可

因为题目需要求的是差分最大值,所以跑最短路然后枚举起点找出差分最大值即可

注意到差分约束如果有解的一个充要条件是图中没有负环,所以需要特判一下

代码:

//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=210;int n,m;int maze[N][N],f[N];int find(int x)
{return f[x]==x?x:f[x]=find(f[x]);
}void merge(int x,int y)
{int xx=find(x),yy=find(y);if(xx!=yy)f[xx]=yy;
}bool check()//是否为二分图
{for(int i=1;i<=n;i++)if(find(i)==find(i+n))return false;return true;
}bool Floyd()//顺便判负环
{for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)maze[i][j]=min(maze[i][j],maze[i][k]+maze[k][j]);for(int i=1;i<=n;i++)if(maze[i][i]<0)return false;return true;
}void init()
{for(int i=1;i<=n<<1;i++)f[i]=i;
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.ans.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);scanf("%d%d",&n,&m);init();for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)maze[i][j]=i==j?0:inf;for(int i=1;i<=m;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);if(w){maze[u][v]=1;maze[v][u]=-1;}else{maze[u][v]=1;maze[v][u]=1;}merge(u,v+n);merge(v,u+n);}if(!check()||!Floyd())//不是二分图或者有负环 return 0*puts("NO");int mmax=-inf,st;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(mmax<maze[i][j]){mmax=maze[i][j];st=i;}puts("YES");printf("%d\n",mmax);for(int i=1;i<=n;i++)printf("%d ",maze[st][i]);puts("");return 0;
}

CodeForces - 1450E Capitalism(差分约束)相关推荐

  1. Codeforces Global Round 12 E. Capitalism 差分约束

    传送门 题意: 思路: 一开始被题意迷惑了,没看出来差分约束,老菜鸡啦.首先看到aj=ai+1a_j=a_i+1aj​=ai​+1可以把aia_iai​分成奇偶,让后这个图就变成一个二分图了.再考虑如 ...

  2. 海亮Day2:差分约束、拓扑排序、欧拉路

    海亮第二天,想着说预习一下的,可是昨天10h+都没有把那六道题打完,就打了四道,上午就讲完课了,还是延续昨天的博客,今天接着总结.. 欧拉路 开头就是特别经典的七桥问题,讲欧拉路一定会讲到的问题,也就 ...

  3. HDU1811 Rank of Tetris 拓扑排序+并查集 OR 差分约束最短路+并查集

    题目链接 题意:就是给你一堆关系,看能不能排出个确定的顺序 做法: 1. 拓扑排序+并查集 应该很容易想到的一种思路,大于小于建立单向边.对于相等的呢,就把他们缩成一个点.就用并查集缩成一个点就行了 ...

  4. HDU3440(差分约束+SPFA算法)

    题意:两栋房子之间的最大距离为D,也就是A-B<=D,现在求出最矮和最高房子之间的最大距离 思路:差分约束+SPFA算法: 当问题可以转化为形如一组 xi‑x'i<=yi 或一组 xi‑x ...

  5. HDU1531(差分约束+Bellman_ford)

    题意:给出一个序列Si = {aSi, aSi+1, ..., aSi+ni} 和其子序列S = {a1, a2, ..., an}:在给出序列的约束条件: aSi + aSi+1 + ... + a ...

  6. poj3159(差分约束)

    题意:其实题目要求的就是这个B-A<=c,所以对应单源最短路径中的d[v]>d[u]+e[u][v] 关于差分约束: 当问题可以转化为形如一组 xi‑x'i<=yi 或一组 xi‑x ...

  7. poj1364(差分约束+Bellman-ford)

    题意:给出一个序列Si = {aSi, aSi+1, ..., aSi+ni} 和其子序列S = {a1, a2, ..., an}:在给出序列的约束条件: aSi + aSi+1 + ... + a ...

  8. poj1201(差分约束+SPFA)

    看到这道题,其实就是和poj1716是差不多的 题意:给出n个闭整数区间[ai,bi]和n个整数C1,.,cn.计算具有区间[ai,bi]的至少ci公共元素的整数集Z的最小大小,对于每一个i=1,2, ...

  9. poj3169(差分约束+SPFA)

    题意:FJ有N头牛,这些牛都站在一条直线上等待,但是现在给出了一些条件: 1.首先列出哪些牛之间彼此喜欢,以及之间的最大距离,也就是A-B<=X 2.随后列出哪些牛之间彼此不喜欢,以及之间的最小 ...

最新文章

  1. 基于stm32f103zet6的DS1302学习
  2. Java基础类库四则运算_00JAVA语法基础_四则运算 01
  3. linux虚拟机网络设置(本机使用公司内网)
  4. dreamweaver 疑问
  5. 2010年第一届蓝桥杯省赛 —— 第二题
  6. 记一次Animator状态快速切换问题的解决
  7. TNG-Hooks:有状态逻辑在标准函数中的重用和组合
  8. 社群经济:如何利用社群做营销?
  9. mysql order by 自定义
  10. Hololens Vuforia 物体识别
  11. python六大数据类型的定义_python六大类标准数据类型和数据类型转换
  12. 4.json字符串转换集json对象、json对象转换json字符串
  13. linux自带python3.5_linux上安装python3, 保留python2
  14. 在线预览PDF(pdfobject)
  15. Spring学习笔记—Spring之旅
  16. 工作学习总结-angular中的安全导航符?.和ts中的非空断言操作符!.
  17. 计算机学院举办 温暖冬日 感恩社会 活动,E·活动 | 我院举办“温暖冬日,感恩社会”活动...
  18. 44 Defending the Theory of Evolution Still Seems Needed
  19. Maxent影响因子响应曲线重绘
  20. 记录vue预渲染prerender-spa-plugin踏坑

热门文章

  1. linux平滑升级nginx,Nginx的平滑重启和平滑升级,nginx
  2. 压缩图片_Word快速压缩图片大小
  3. NofairSync.tryAcquire
  4. 完成AOP 顶层设计-AopProxy
  5. 微服务架构的实施现状
  6. Spring抽取jdbc配置文件
  7. Sping Cloud Eureka
  8. 超时机制,断路器模式简介
  9. plsql(轻量版)-存储函数存储过程
  10. docker里面装mysql_docker中安装及使用mysql