• bzoj 3436小K的农场


    3436: 小K的农场
    Time Limit: 10 Sec Memory Limit: 128 MB
    Submit: 2327 Solved: 1105
    [Submit][Status][Discuss]
    Description
    背景
    小K是个特么喜欢玩MC的孩纸。。。
    描述
    小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得
    一些含糊的信息(共m个),以下列三种形式描述:农场a比农场b至少多种植了c个单位的作物,农场a比农场b至多
    多种植了c个单位的作物,农场a与农场b种植的作物数一样多。但是,由于小K的记忆有些偏差,所以他想要知道存
    不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。
    Input
    第一行包括两个整数n和m,分别表示农场数目和小K记忆中的信息的数目接下来m行:如果每行的第一个数是1,接
    下来有三个整数a,b,c,表示农场a比农场b至少多种植了c个单位的作物如果每行第一个数是2,接下来有三个整数a
    ,b,c,表示农场a比农场b至多多种植了c个单位的作物如果每行第一个数是3,接下来有两个整数a,b,表示农场a
    种植的数量与b一样。1<=n,m,a,b,c<=10000
    Output
    如果存在某种情况与小K的记忆吻合,输出”Yes”,否则输出”No”

    Sample Input
    3 3

    3 1 2

    1 1 3 1

    2 2 3 2
    Sample Output
    Yes

    样例解释

    三个农场种植的数量可以为(2,2,1)
    HINT
    Source
    Kpmcup#0 By Greens

    [Submit][Status][Discuss]
    
    题目中给出了一些不等式的关系 最后询问是否存在合法方案。

    这显然是差分约束的模型。对于一样多 a==b 我们将其转换为 a>=b,b>=a即可。

    对于 a>=b+c 我们考虑最短路模型中的 dis[tn]<=dis[x]+e[i]; 这个意味着x向tn连了一条边权为e[i]的边。

    观察这个不等关系 b+c<=a b<=a-c 那么意味着a向b连了一条-c的边。

    对于a<=b+c 这个意味着a向b连了一条c的边。

    考虑什么时候无解 显然出现负环的时候是无解的因为此时 很多约束关系不成立,所以会成环。

    从哪个点开始?一般做法是建立超级源点 然后超级源点向每个点都连上一条边权为0的边开始跑。

    但是 我们可以直接把这些点放到队列里 开始跑。

    为什么要这样做?考虑我们初始构造解为0 如果不满足约束关系那么一些点的dis会被更新 存在负环也是如此 所以这样做是对的。

    int n,m,len;
    queue<int>q;
    int dis[MAXN],c[MAXN],vis[MAXN];
    int lin[MAXN],ver[MAXN],nex[MAXN],e[MAXN];
    inline void add(int x,int y,int z)
    {
    	ver[++len]=y;
    	nex[len]=lin[x];
    	lin[x]=len;
    	e[len]=z;
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	n=read();m=read();
    	for(int i=1;i<=n;++i)q.push(i),vis[i]=1;
    	for(int i=1;i<=m;++i)
    	{
    		int op,x,y;
    		op=read();x=read();y=read();
    		if(op==1)add(x,y,-read());
    		if(op==2)add(y,x,read());
    		if(op==3)add(x,y,0),add(y,x,0);
    	}
    	while(q.size())
    	{
    		int x=q.front();vis[x]=0;q.pop();
    		for(int i=lin[x];i;i=nex[i])
    		{
    			int tn=ver[i];
    			if(dis[tn]>dis[x]+e[i])
    			{
    				dis[tn]=dis[x]+e[i];
    				c[tn]=c[x]+1;
    				if(c[tn]>=n){puts("No");return 0;}
    				if(!vis[tn])q.push(tn),vis[tn]=1;
    			}
    		}
    	}
    	printf("Yes");
    	return 0;
    }
    
  • 相关阅读:
    接口的理解
    Application.DoEvents()笔记
    c#的DateTime.Now函数详解---来源(笨鸟先飞)
    怎么判断字符串a的内容包含字符串b的内容
    c#下怎么判断一个字符串是否可以转换为double类型
    .net中TreeView使用方法小结(2)
    .net中TreeView使用方法小结(1)
    TT企业微信社群辅助,企业微信社群辅助工具,允许批量添加好友,自动同意添加请求,自动回复消息
    TokenMismatchException Laravel
    实现Nginx Upload 模块 功能上传文件。
  • 原文地址:https://www.cnblogs.com/chdy/p/12459524.html
Copyright © 2020-2023  润新知