| 小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 */