zoukankan      html  css  js  c++  java
  • [BZOJ3436]小K的农场

    题目描述 Description###

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

    输入描述 Input Description###

    第一行包括两个整数(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 Description###

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

    样例输入 Sample Input###

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

    样例输出 Sample Output###

    Yes
    

    数据范围及提示 Data Size & Hint###

    三个农场种植数量可以为(2,2,1)。
    对于100%的数据 (1<=n,m,a,b,c<=10000) .

    之前的一些废话###

    停课第二天,继续努力!

    题解###

    查分约束系统裸题。我们考虑一个图中的一条边(Edge(u,v,w)) ,(dis_u) 表示源点到u的最短路,满足这个性质:(dis_u + wgeq dis_v) ,所以我们可以考虑用这个性质建图。本题中的性质1是这样的:(dis_ageq dis_b+c) ,我们通过移项变号一系列的操作,变成了:(dis_a-cgeq dis_b) ,即a向b连一条-c的边。对于性质2:(dis_aleq dis_b+2) ,即b向a连一条c的边,对于性质3,我们直接在a与b之间连一条双向权值为0的边即可。然后我们来思考何时满足题意,当有一组解满足题意时,即所有点的(dis) 都确定了,当无解的时候,所有的(dis) 都无法确定,很显然就是判一个图中是否带有负环。

    代码###

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> PII;
    #define mem(a,b) memset(a,b,sizeof(a))
    inline int read()
    {
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    const int maxn=10010;
    struct Edge
    {
    	int u,v,w,next;
    	Edge() {}
    	Edge(int _1,int _2,int _3,int _4):u(_1),v(_2),w(_3),next(_4) {}
    }e[maxn<<1];
    int n,m,Q1[maxn],a[maxn],b[maxn],c[maxn],ce=-1,first[maxn],dis[maxn],cnt[maxn];
    bool vis[maxn],VIS[maxn];
    queue<int> Q;
    void addEdge(int a,int b,int c){e[++ce]=Edge(a,b,c,first[a]);first[a]=ce;}
    bool SPFA()
    {
    	mem(dis,42);
    	Q.push(0);vis[0]=1;dis[0]=0;cnt[0]=1;
    	while(Q.size())
    	{
    		int now=Q.front();Q.pop();
    		for(int i=first[now];i!=-1;i=e[i].next)
    		    if(dis[now]+e[i].w<dis[e[i].v])
    		    {
    		    	dis[e[i].v]=dis[now]+e[i].w;
    		    	if(!vis[e[i].v])
    				{
    					Q.push(e[i].v);
    					vis[e[i].v]=1;
    					cnt[e[i].v]++;
    					if(cnt[e[i].v]>n+1)return 0;
    				} 
    			}
    		vis[now]=0;
    	}
    	return 1;
    }
    int main()
    { 
    	mem(first,-1);
    	n=read();m=read();
    	for(int i=1;i<=m;i++)
    	{
    		Q1[i]=read();a[i]=read(),b[i]=read();
    		if(Q1[i]==1)c[i]=read(),addEdge(a[i],b[i],-c[i]);
    		else if(Q1[i]==2)c[i]=read(),addEdge(b[i],a[i],c[i]);
    		else if(Q1[i]==3)addEdge(a[i],b[i],0),addEdge(b[i],a[i],0); 
    	}
    	for(int i=1;i<=n;i++)addEdge(0,i,0); 
    	if(SPFA())printf("Yes
    ");
    	else printf("No
    ");
    	return 0;
    }
    

    总结###

    md调了好长时间发现没有输入c...以后判一个图是否带有负环最好创建一个0号节点向所有的节点连一条权值为0的边,保证整个图联通,好判负环。注意判负环的条件是(cnt[now]>n) (n为节点总数(包括0号点))

  • 相关阅读:
    《模糊测试--强制发掘安全漏洞的利器》阅读笔记(一)
    BrickerBot
    这些写的很好的PCA文章
    决策树(挖坑待填)
    线性回归
    关于给定DNA序列,如何找到合理的切割位点使得其退火温度保持相对一致
    生成全排列
    AVL树学习笔记
    二叉搜索树
    堆排序
  • 原文地址:https://www.cnblogs.com/FYH-SSGSS/p/7725368.html
Copyright © 2011-2022 走看看