【BZOJ2330】糖果(差分约束系统,强连通分量,拓扑排序)
题意:
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
输入的第一行是两个整数N,K。
接下来K行,表示这些点需要满足的关系,每行3个数字,X,A,B。
如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;
如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;
如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;
如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;
如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;
对于所有的数据,保证 N<=100000,K<=100000,1<=X<=5,1<=A, B<=N
思路:第一反应应该是差分约束系统,但N的范围令人不放心,实际上裸SPFA也需要一些优化才能跑过去
知乎上有几位大佬说这题是tarjan缩点+拓扑排序,确实这种做法理论复杂度才是有保证的
先建立原图,对于等于关系连双向边,小于等于(和大于等于,显然等价)连单向边,先缩一次点,同一个分量里的人糖果数一定相等
再进行拓扑排序计算每一个分量的糖果数,环会导致无解,注意糖果数和前面推导不同时需要取MAX
最后特判下同一个分量里的边有没有不等的,有则无解
SPFA
var q:array[..]of longint;
head,vet,next,len,dis,time:array[..]of longint;
inq:array[..]of boolean;
n,m,i,x,a,b,tot:longint;
ans,tmp:int64; procedure add(a,b,c:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
len[tot]:=c;
head[a]:=tot;
end; procedure spfa;
var t,w,i,u,e,v:longint;
begin
fillchar(time,sizeof(time),);
t:=; w:=-;
for i:= to n do
begin
dis[i]:=; inc(w); q[w]:=i; inq[i]:=true;
end; while t<=w do
begin
u:=q[t mod n]; inc(t); inq[u]:=false;
e:=head[u];
while e<> do
begin
v:=vet[e];
if dis[u]+len[e]>dis[v] then
begin
dis[v]:=dis[u]+len[e];
if not inq[v] then
begin
inc(time[v]);
if time[v]>n then
begin
writeln(-); ans:=-;
exit;
end;
inc(w); q[w mod n]:=v; inq[v]:=true;
end;
end;
e:=next[e];
end;
end;
end; begin read(n,m);
for i:= to m do
begin
read(x,a,b);
if (x and =)and(a=b) then
begin
writeln(-);
exit;
end;
case x of
:begin add(b,a,); add(a,b,); end;
:add(a,b,);
:add(b,a,);
:add(b,a,);
:add(a,b,);
end;
end;
spfa;
if ans= then
begin
for i:= to n do ans:=ans+dis[i]; writeln(ans);
end; end.
tarjan+拓扑排序
#include<map>
#include<set>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int M=;
int head[M],vet[M],next[M],len[M],a[M],b[M],c[M],dfn[M],low[M],flag[M],ind[M],stack[M],s[M];
int n,m,i,tot,id,top,cnt;
long long d[M],size[M]; void add(int a,int b,int c)
{
next[++tot]=head[a];
vet[tot]=b;
len[tot]=c;
head[a]=tot;
ind[b]++;
} void swap(int &a,int &b)
{
int t;
t=a;a=b;b=t;
} void dfs(int u)
{
int e,v;
flag[u]=;
stack[++top]=u;
dfn[u]=low[u]=++cnt;
for(e=head[u];e;e=next[e])
{
v=vet[e];
if(!flag[v])
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(!s[v]) low[u]=min(low[u],low[v]);
}
if(low[u]==dfn[u])
{
id++;
while(stack[top]!=u)
{
s[stack[top]]=id;
size[id]++;
top--;
}
s[stack[top]]=id;
size[id]++;
top--;
} } long long solve()
{
queue<int> q;
int num;
long long sum;
for(int i=;i<=id;i++)
if(!ind[i])
{
q.push(i);
d[i]=;
}
if(q.empty()) return -;
num=;
while(!q.empty())
{
int u=q.front(); q.pop(); num++;
for(int e=head[u];e;e=next[e])
{
int v=vet[e];
ind[v]--;
d[v]=max(d[v],d[u]+len[e]);
if(!ind[v]) q.push(v);
}
}
if(num<id) return -;
else
{
sum=;
for(int i=;i<=id;i++) sum=sum+d[i]*size[i];
return sum;
} } int main()
{
// freopen("bzoj2330.in","r",stdin);
// freopen("bzoj2330.out","w",stdout);
scanf("%d%d",&n,&m);
id=;
for(i=;i<=m;i++)
{
scanf("%d%d%d",&a[i],&b[i],&c[i]);
if(a[i]==||a[i]==) swap(b[i],c[i]);
if(a[i]==)
{
add(b[i],c[i],);
add(c[i],b[i],);
}
if(a[i]==||a[i]==) add(b[i],c[i],);
}
for(i=;i<=n;i++)
if(!flag[i]) dfs(i);
//printf("%d\n",id);
memset(head,,sizeof(head));
memset(ind,,sizeof(ind));
tot=;
for(i=;i<=m;i++)
if(s[b[i]]!=s[c[i]])
{
if(a[i]==||a[i]==) add(s[b[i]],s[c[i]],);
else add(s[b[i]],s[c[i]],);
}
else
{
if(a[i]==||a[i]==)
{
printf("-1\n");
return ;
}
}
printf("%lld\n",solve());
return ;
}
【BZOJ2330】糖果(差分约束系统,强连通分量,拓扑排序)的更多相关文章
- BZOJ_3887_[Usaco2015 Jan]Grass Cownoisseur_强连通分量+拓扑排序+DP
BZOJ_3887_[Usaco2015 Jan]Grass Cownoisseur_强连通分量+拓扑排序+DP Description In an effort to better manage t ...
- BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset
BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i ...
- poj 2762(强连通分量+拓扑排序)
题目链接:http://poj.org/problem?id=2762 题意:给出一个有向图,判断任意的两个顶点(u,v)能否从u到达v,或v到达u,即单连通,输出Yes或No. 分析:对于同一个强连 ...
- BZOJ1924:[SDOI2010]所驼门王的宝藏(强连通分量,拓扑排序)
Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室 ...
- 2019ICPC(银川) - Delivery Route(强连通分量 + 拓扑排序 + dijkstra)
Delivery Route 题目:有n个派送点,x条双向边,y条单向边,出发点是s,双向边的权值均为正,单向边的权值可以为负数,对于单向边给出了一个限制:如果u->v成立,则v->u一定 ...
- CDOJ 图论专题 A.不是图论 强连通分量+拓扑排序 经典
题目链接 在其中纠错第一次wa代码 #include <cstdio> #include <cstring> #include <cstdlib> #includ ...
- POJ 2762 Going from u to v or from v to u?(强连通分量+拓扑排序)
职务地址:id=2762">POJ 2762 先缩小点.进而推断网络拓扑结构是否每个号码1(排序我是想不出来这点的. .. ).由于假如有一层为2的话,那么从此之后这两个岔路的点就不可 ...
- bzoj2330: [SCOI2011]糖果 差分约束系统
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候 ...
- 【bzoj2330】[SCOI2011]糖果 差分约束系统
题目描述 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配 ...
- [BZOJ2330][SCOI2011]糖果 差分约束系统+最短路
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2330 类似于题目中这种含有不等式关系,我们可以建立差分约束系统来跑最长路或最短路. 对于一 ...
随机推荐
- Android系统的启动流程
手机启动后首先会通过执行BootLoader来启动Linux内核,BootLoader是所有嵌入式设备开机启动执行的第一行代码,linux内核在启动过程中会加载各种设备的驱动同时初始化数据结构,并且开 ...
- 转】MongoDB 自动分片 auto sharding
原博文出自于: http://blog.fens.me/category/%E6%95%B0%E6%8D%AE%E5%BA%93/page/4/ 感谢! MongoDB 自动分片 auto shard ...
- [ SDOI 2010 ] 古代猪文
\(\\\) Description 一句话题意: 设 \(x=\sum_{d|n} C_n^d\),求 \(G^x\pmod {999911659}\) . 从原题面大段语文中其实不难推出所求. \ ...
- CF932C Permutation Cycle
思路: 构造. 实现: #include <bits/stdc++.h> using namespace std; ]; int main() { int n, a, b; while ( ...
- 行内元素对齐各种问题--从line-height和vertical-align的角度分析
最近研究行内元素的对齐问题,发现img不管怎么设置,下边都有一块留白,强迫症无法忍受未知,于是开始了查阅探索之旅. 辗转来到张鑫旭的博客,他对行内盒子模型做了详细的介绍,包括“幽灵节点”,“line- ...
- 临时笔记 Protection
如果操作系统不使用处理器的多任务机制,它仍然需要为栈创建至少一个TSS 当程序通过调用门改变特权级的时候,处理器执行下面的步骤切换栈,并且执行被调用的程序在新的特权级 1. 使用目标代码段的DPL从T ...
- 合并百度影音的离线数据 with python 2.2 bdv格式的更新
百度影音的bdv格式又有变化. 此次存在2种bdv格式. 格式1:每个文件夹内就一个bdv文件,文件合并后改名avi即可. 格式2:每个文件夹内一个bdv文件作为索引,其他附加guid的文件作为数据. ...
- 自动交互脚本之expect使用记录
之前一直没怎么用这个命令,意外用了一下,还不错,那这个是干嘛的呢 我们或多或少会远程登录其他服务器,需要执行某项任务,通常需要手动接入,输入密码啊,等等 那我们如何有效的自动执行呢,expect可以解 ...
- switch、try-catch
记录 1. 使用对象代替 switch 和 if-else 2. 根据返回数据是否能转成对象,取值 如果返回是数字字符串,直接返回,如果返回是对象,取对应的key值,再返回 其它情况,返回空 {{ o ...
- 笔试算法题(43):布隆过滤器(Bloom Filter)
议题:布隆过滤器(Bloom Filter) 分析: BF由一个很长的二进制向量和一系列随机映射的函数组成,通过多个Hash函数将一个元素映射到一个Bit Array中的多个点,查询的时候仅当所有的映 ...