题目大意

有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类:

1.给出a,b (1<=a,b<=n),要求满足Xa + 1 = Xb

2.给出c,d (1<=c,d<=n),要求满足Xc <= Xd

在满足所有限制的条件下,求集合{Xi}大小的最大值。

分析

差分约束,问题很新颖

注意到图有特殊性

限制1(1类边):双向边

限制2(2类边):单向边

我们考虑求强联通分量

连接两个强联通分量的边不可能是1类边(不然强联通就合起来了)

只可能是A<=B

只要保证A中最大值小于B中最小值,就可以使不同权值最多

一定是可以做到的

那么我们只需要对每个强联通求出答案再累加起来就好了

对于强联通中的2类边,一定是在一个环中的,一定都为一个权值(不然就分成两个连通块了)

这一部分的最长路跑出来是0

由于图中只有-1,0,1三种边

每个强联通中,

记D为任意两个点的 最长路的绝对值 的最大值

其实D就是最大权值和最小权值的差

所以每个连通块权值种类就是D+1

姿势

1.差分约束常常特判连边是否自环矛盾

2.floyd判负环可以一开始f[i][i]=0,跑floyd的时候不判i!=j!=k,跑完后看看f[i][i]有没有变

3.邻接矩阵建图注意重编时取max,min啥的

4.之前我tarjan一直是写错的

if(inst[y]) low[x]=min(low[x],dfn[y]);//注意这里是inst[i],因为有向图搜索顺序的问题,tarjan是可能跑到之前tarjan过的地方的,如果写if(dfn[y])这样会出bug
else if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}

5.spfa时用que[],inq[]

6.spfa时inc函数既写引用又写返回值,方便一些

solution

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
const int M=607;
const int N=100007;
const int INF=2139062144; inline int rd(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
} int n,m1,m2; int g[M],te;
struct edge{
int y,d,next;
}e[N<<1];
struct node{
int x,y;
node(int xx=0,int yy=0){x=xx;y=yy;}
}e1[N],e2[N]; void addedge(int x,int d,int y){
e[++te].y=y;e[te].d=d;e[te].next=g[x];g[x]=te;
} int dfn[M],low[M],tdfn;
int col[M],cnt;
int st[M],tot;
int vis[M];
int f[M][M];
int ans[M];
int inst[M]; void tarjan(int x){
dfn[x]=low[x]=++tdfn;
st[++tot]=x;
inst[x]++;
int p,y;
for(p=g[x];p;p=e[p].next){
y=e[p].y;
if(inst[y]) low[x]=min(low[x],dfn[y]);//instack
else if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}
}
if(low[x]==dfn[x]){
++cnt;
while(st[tot]!=x){
inst[st[tot]]=0;
col[st[tot--]]=cnt;
}
inst[st[tot]]=0;
col[st[tot--]]=cnt;
}
} void floyd(){
int i,j,k;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(f[i][k]!=-INF&&f[k][j]!=-INF){
f[i][j]=max(f[i][j],f[i][k]+f[k][j]);
}
} int main(){ n=rd(),m1=rd(),m2=rd(); int i,j,x,y; for(i=1;i<=m1;i++){
x=rd(),y=rd();
if(x==y){//²é·ÖÔ¼Êø³£¼ûÌØÅÐ
puts("NIE");
return 0;
}
e1[i]=node(x,y);
addedge(x,1,y);
addedge(y,-1,x);
} for(i=1;i<=m2;i++){
x=rd(),y=rd();
e2[i]=node(x,y);
addedge(x,0,y);
} for(i=1;i<=n;i++)
if(!dfn[i])
tarjan(i); memset(f,128,sizeof(f));
for(i=1;i<=m1;i++){
x=e1[i].x,y=e1[i].y;
if(col[x]==col[y]){
f[x][y]=max(f[x][y],1);
f[y][x]=max(f[y][x],-1);
}
}
for(i=1;i<=m2;i++){
x=e2[i].x,y=e2[i].y;
if(col[x]==col[y]){
f[x][y]=max(f[x][y],0);
}
}
for(i=1;i<=n;i++) f[i][i]=0;//Åиº»·Óà floyd(); for(i=1;i<=n;i++) if(f[i][i]>0){
puts("NIE");
return 0;
} for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(col[i]==col[j]&&f[i][j]!=-INF) ans[col[i]]=max(ans[col[i]],abs(f[i][j]));///abs int sum=0;
for(i=1;i<=cnt;i++) sum+=ans[i]+1; printf("%d\n",sum); return 0;
}

bzoj 2788 [Poi2012]Festival 差分约束+tarjan+floyd的更多相关文章

  1. [Poi2012]Festival 差分约束+tarjan

    差分约束建图,发现要在每个联通块里求最长路,600,直接O(n3) floyed #include<cstdio> #include<cstring> #include< ...

  2. BZOJ_2788_[Poi2012]Festival_差分约束+tarjan+floyed

    BZOJ_2788_[Poi2012]Festival_差分约束+tarjan+floyed Description 有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类: ...

  3. BZOJ 2330 SCOI2011糖果 差分约束

    2330: [SCOI2011]糖果 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2819  Solved: 820 题目连接 http://www ...

  4. bzoj 2330 [SCOI2011]糖果 差分约束模板

    题目大意 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配 ...

  5. bzoj 4500: 矩阵【差分约束】

    (x,y,z)表示格子(x,y)的值为z,也就是x行+y列加的次数等于z,相当于差分约束的条件,用dfs判断冲突即可. #include<iostream> #include<cst ...

  6. BZOJ 2330: [SCOI2011]糖果( 差分约束 )

    坑爹...要求最小值要转成最长路来做.... 小于关系要转化一下 , A < B -> A <= B - 1 ------------------------------------ ...

  7. [BZOJ2788][Poi2012]Festival

    2788: [Poi2012]Festival Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 187  Solved: 91[Submit][Statu ...

  8. 【BZOJ1077】天平(差分约束)

    [BZOJ1077]天平(差分约束) 题面 BZOJ 洛谷 题解 利用矩阵可以很容易得到两个点之间的最大差和最小差,再利用这个信息判断即可.差分约束用\(Floyd\)计算.时间复杂度\(O(n^3) ...

  9. 【题解】 [POI2012]FES-Festival (差分约束)

    懒得复制题面,戳我戳我 Question: (因为网上找不到好的翻译,这里简单复述一下) 告诉你\(m1+m2\)个约束条件,然后要你找出\(X_1-X_n\)这些数字,求满足要求的数列中不同的数字个 ...

随机推荐

  1. exportfs: /mnt/demo requires fsid= for NFS export

    解决方法:/mnt/demo 10.0.1.57(fsid=0,rw,async) //加入fsid=0参数就可.

  2. 一些恶搞人的c++程序

    top1: 不停打开的cmd(磁盘操作系统) 代码如下: #include<windows.h> using namespace std; int main() { system(&quo ...

  3. Unity基础-脚本的优化

    脚本的优化 object pool 避免频繁的内存分配和gc噩梦(字符串相加?) 是否有必要都写在update里?分帧? 需要的只取一次 使用editor内赋值,而不是find 复杂的物理 复杂的数学 ...

  4. 文件处理seek以及修改内容的两种方式

    f.seek(offset,whence)offset代表文件的指针的偏移量,单位是字节byteswhence代表参考物,有三个取值# 0:参照文件的开头# 1:参照当前文件指针所在位置# 2: 参照 ...

  5. Python模块(二)(序列化)

    1. namedtuple 命名元组->类似创建了一个类 from collections import namedtuple p = namedtuple("Point", ...

  6. leetcode-26-exercise_linked-list

    141. Linked List Cycle Given a linked list, determine if it has a cycle in it. 解题思路: 需要检查before和afte ...

  7. 水题:51Nod1095-Anigram单词

    1095 Anigram单词 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 Description 一个单词a如果通过交换单词中字母的顺序可以得到另外的单词b,那 ...

  8. C++实现Behavioral - Observer模式 (转)

    转http://patmusing.blog.163.com/blog/static/13583496020101501923571/ 也称为Dependents或Publish-Subscribe模 ...

  9. 封装BackgroundWorker控件(提供源代码下载,F5即可见效果)

    Demo源码 背景 经常做些小程序或者小DEMO的时候会用到异步,多线程来执行一些比较耗时的工作同时将进度及时进行反馈.我通常会使用位于[ System.ComponentModel]命名空间下的Ba ...

  10. 在O(1)时间内删除链表结点 【微软面试100题 第六十题】

    题目要求: 给定链表的头指针和一个结点指针,在O(1)时间删除该结点. 参考资料:剑指offer第13题. 题目分析: 有几种情况: 1.删除的结点是头结点,且链表不止一个结点: 2.删除的结点是头结 ...