小K的农场
难度级别:C; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
试题描述
小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m个),以下列三种形式描述:农场a比农场b至少多种植了c个单位的作物,农场a比农场b至多多种植了c个单位的作物,农场a与农场b种植的作物数一样多。但是,由于小K的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。
输入
第一行包括两个整数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一样多。
输出
如果存在某种情况与小K的记忆吻合,输出“Yes”,否则输出“No”。
输入示例
3 3
3 1 2
1 1 3 1
2 2 3 2
输出示例
Yes
其他说明
三个农场种植数量可以为(2,2,1)。
对于100%的数据  1<=n,m,a,b,c<=10000.
 

小K的农场差分约束系统,用DFS的SPFA来判会快好多

#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=10010;
const int maxm=20010;
struct SPFA {
    int n,m,first[maxn],next[maxm];
    struct Edge {int from,to,dist;}edges[maxm];
    void init(int n) {
        this->n=n;m=0;
    }
    void AddEdge(int u,int v,int w) {
        edges[++m]=(Edge){u,v,w};next[m]=first[u];first[u]=m;
    }
    int vis[maxn],d[maxn];
    int dfs(int x) {
        if(vis[x]) return 1;vis[x]=1;
        ren {
            Edge& e=edges[i];
            if(d[e.to]>d[x]+e.dist) {
                d[e.to]=d[x]+e.dist;
                if(dfs(e.to)) return 1;
            }
        }
        vis[x]=0;return 0;
    }
    int check() {
        rep(i,1,n) vis[i]=d[i]=0;
        rep(i,1,n) if(dfs(i)) return 1;
        return 0;
    }
}sol;
int main() {
    int n=read(),m=read();sol.init(n);
    rep(i,1,m) {
        int t=read();
        if(t==3) {
            int x=read(),y=read();
            sol.AddEdge(x,y,0);sol.AddEdge(y,x,0);
        }
        else if(t==1) {
            int x=read(),y=read(),v=read();
            sol.AddEdge(x,y,-v);
        }
        else {
            int x=read(),y=read(),v=read();
            sol.AddEdge(y,x,v);
        }
    }
    puts(sol.check()?"No":"Yes");
    return 0;
}
/*
3 2
3 1 2
1 1 2 1
*/
View Code

相关文章: