【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 类似于题目中这种含有不等式关系,我们可以建立差分约束系统来跑最长路或最短路. 对于一 ...
随机推荐
- Objective-c单例模式的正确写法--用dispatch 线程安全
单例模式在iOS开发中可能算是最常用的模式之一了,但是由于oc本身的语言特性,想要写一个正确的单例模式相对来说比较麻烦,这里我就抛砖引玉来聊一聊iOS中单例模式的设计思路.关于单例模式更多的介绍请参考 ...
- Oracle事务控制语言
事务控制语言在各大数据库中都差不多,本文讲讲Oracle和别的数据库不一样的地方 Oracle每条sql语句都是一个事务,像insert.update.delete之类的,每次执行过都要commit提 ...
- XCode的debug断点调试
debug 流程控制 当你通过 Xcode 的源码编辑器的侧边槽 (或者通过下面的方法) 插入一个断点,程序到达断点时会就会停止运行. 调试条上会出现四个你可以用来控制程序的执行流程的按钮. 从左到右 ...
- LigerUI用Post\Get\Ajax前后台交互方式的写法
parms 参数统一 json格式的数据 url 访问后台的url 设置同步参数 [javascript] view plain copy $.ajaxSetup({ async : false} ...
- q-oo-p , a piggy domain name. Very cute. boyan.zheng at foxmail.com
Contact me.
- https://quotefancy.com/ 经典句子(英语) 真是特别好~
https://quotefancy.com/ 经典句子(英语)
- Java 斜杠 与 反斜杠
除号 /(数字键盘的斜杠)网址 /(数字键盘的斜杠)文件地址 \转义 \正则表达式 \
- Laravel Excel模板导出-带图片
Laravel Excel版本 3.1 1.数据准备 建个2个表,加点数据,控制器中查数据,给模板使用. 表1-order:id, order_no, img_path, note 表2-order_ ...
- LPCTSTR 字符串获取其长度
LPCTSTR lpStr = "123456789";int i=CString(lpStr).GetLength();
- JS日期,金钱处理
一丶获取两个时间的天数 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> ...