注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

TsReaper的博客

一起来玩算法竞赛吧~

 
 
 
 
 

日志

 
 

[题解]小K的农场  

2015-08-04 11:51:23|  分类: 题解 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
关键字:差分约束。

Link&Limit


        [洛谷1993]  [BZOJ3436]
        时间限制:1000ms  空间限制:131072kb

Description


        小 K 在 Minecraft 里面建立很多很多的农场,总共 n 个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共 m 个),以下列三种形式描述:
        1. 农场 a 比农场 b 至少多种植了 c 个单位的作物。
        2. 农场 a 比农场 b 至多多种植了 c 个单位的作物。
        3. 农场 a 与农场 b 种植的作物数一样多。
        但是,由于小 K 的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。

Input Format


        第一行包括两个整数 n 和 m,分别表示农场数目和小 K 记忆中的信息数目。
        接下来 m 行:
        如果每行的第一个数是 1,接下来有 3 个整数 a,b,c,表示农场 a 比农场 b 至少多种植了 c 个单位的作物。
        如果每行的第一个数是 2,接下来有 3 个整数 a,b,c,表示农场 a 比农场 b 至多多种植了 c 个单位的作物。
        如果每行的第一个数是 3,接下来有 2 个整数 a,b,表示农场 a 终止的数量和 b 一样多。

Output Format


        如果存在某种情况与小 K 的记忆吻合,输出“Yes”,否则输出“No”。

Sample Input #1


3 3
3 1 2
1 1 3 1
2 2 3 2

Sample Output #1


Yes

Hint


        对于 100% 的数据保证:1 ≤ n,m,a,b,c ≤ 10000。

        差分约束的裸题。如果构造出来的图中有正环(要算最长路)就是No,否则就是Yes。找正环可以用spfa来做,如果一个点入队超过n次则图中含有正环。不过本题的数据范围这样做可能超时,加个限制会好很多。
        差分约束的介绍可见:http://tsreaper.blog.163.com/blog/static/250132006201574103730108/
        找环也可以用递归版的spfa:http://hzwer.com/3600.html

#include <stdio.h>
#define QLEN 10005
int n,m;
int e[30010][3],p[10010],tot = 0;
int q[10010],dis[10010],cnt[10010],head,tail,ttail = 0;
short vis[10010];
void adde(int sn,int fn,int val)
{
e[++tot][0] = fn; e[tot][1] = val; e[tot][2] = p[sn]; p[sn] = tot;
}
short spfa()
{
int i,sn,fn,val;
for(i=1;i<=n;i++) dis[i] = -999999999;
head = 1; tail = ttail = 2;
vis[0] = 1; cnt[0]++;
while(head!=tail)
{
if(ttail>1000000) return 0;
sn = q[head++];
for(i=p[sn];i;i=e[i][2])
{
fn = e[i][0]; val = e[i][1];
if(dis[fn]>=dis[sn]+val) continue;
dis[fn] = dis[sn]+val;
if(vis[fn]) continue;
vis[fn] = 1; q[tail++] = fn; cnt[fn]++; ttail++;
if(cnt[fn]>n) return 0;
if(tail>QLEN) tail = 1;
}
vis[sn] = 0;
if(head>QLEN) head = 1;
}
return 1;
}
int main()
{
int i,opt,sn,fn,val;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++) adde(0,i,0);
for(i=1;i<=m;i++)
{
scanf("%d",&opt);
if(opt == 1)
{
scanf("%d%d%d",&sn,&fn,&val);
adde(fn,sn,val);
}
else if(opt == 2)
{
scanf("%d%d%d",&sn,&fn,&val);
adde(sn,fn,-val);
}
else
{
scanf("%d%d",&sn,&fn);
adde(sn,fn,0); adde(fn,sn,0);
}
}
if(spfa()) printf("Yes");
else printf("No");
return 0;
}

  评论这张
 
阅读(8)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018