小总结:
把条件转换成 “ a - b < c ” 类似的,按 b -> a 的方向权值为 c 建边,求最短路。
练习:
P1993 小K的农场 【模板】
题目描述
小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”。
1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostream> 6 #define re register 7 #define in inline 8 #define ll long long 9 #define N 100010 10 using namespace std; 11 const int inf=2147483647; 12 in int read(){ 13 int x=0,f=1; char c=getchar(); 14 while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} 15 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 16 return x*f; 17 } 18 struct node{ 19 int nxt,to,w; 20 }edge[N*3]; 21 int n,m,cnt; 22 int head[N*3],tot[N],vis[N],dis[N]; 23 24 in void add(int x,int y,int w){ 25 edge[++cnt].nxt=head[x]; 26 edge[cnt].to=y; 27 edge[cnt].w=w; 28 head[x]=cnt; 29 } 30 void spfa(){ 31 queue <int > q; 32 for(int i=1;i<=n;i++) dis[i]=inf; 33 vis[0]=1,q.push(0); 34 while(!q.empty()){ 35 int u=q.front(); 36 q.pop(),vis[u]=0; 37 for(int i=head[u];i;i=edge[i].nxt){ 38 int v=edge[i].to; 39 if(dis[v]>dis[u]+edge[i].w){ 40 dis[v]=dis[u]+edge[i].w; 41 if(!vis[v]) 42 { 43 q.push(v),vis[v]=1; 44 if(tot[v]==20){printf("No");exit(0);} 45 tot[v]++; 46 } 47 } 48 } 49 } 50 } 51 int main() 52 { 53 n=read(),m=read(); 54 while(m--){ 55 int t=read(),u=read(),v=read(),w; 56 if(t==3) add(u,v,0),add(v,u,0); 57 else if(t==2) w=read(),add(v,u,w); 58 else w=read(),add(u,v,-w); 59 } 60 for(re int i=n;i>=1;i--) add(0,i,1); 61 spfa(); 62 printf("Yes"); 63 return 0; 64 }