本天的第二道题解。(感觉今天的题都很有价值呢)
那么放送题目。
题目描述 小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”。
其实这就是一道差分约束的大水题啦
那么我们这题的思路是什么呢?
首先,根据题面,我们可以了解到三个不等式:
- a-b>=c;
- a-b<=c;
- a==b;
那么我们根据差分约束可以很容易的把其中的式子转换成我们想要的--> b-a>=c!;
那么我们就可以根据上面的几个不等式来建图了。
我们把一条从a到b的路上的权值记录为从b到a的差值,跑一边最短路就好了啊。
顺便一提,这题不卡SPFA耶!!兴奋。
那么,代码放送时间到!!(请别介意数组名称和函数名,可能只是一种执念QAQ)
#include<bits/stdc++.h> #define inf 100000000 #define N 10005 using namespace std; int n,m; int head[N],ecnt,dis[N]; struct Edge{ int from,to,dis,nxt; }edge[N*3]; bool vis[N]; inline int read() { int a=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') { a=a*10+ch-'0'; ch=getchar();} return a; } void add(int u,int v,int dis){ ++ecnt; edge[ecnt].dis=dis; edge[ecnt].from=u; edge[ecnt].to=v; edge[ecnt].nxt=head[u]; head[u]=ecnt; } bool spfa(int u) { vis[u]=1; for(int i=head[u];i;i=edge[i].nxt) { if(dis[edge[i].to]<dis[u]+edge[i].dis) { dis[edge[i].to]=dis[u]+edge[i].dis; if(vis[edge[i].to]) return 0; if(!spfa(edge[i].to)) return 0; } } vis[u]=0; return 1; } int main() { n=read(); m=read(); for(int i=1;i<=m;i++) { int x,a,b,c; x=read(); if(x==1) { a=read(); b=read(); c=read(); add(a,b,c); } if(x==2) { b=read(); a=read(); c=read(); c*=-1; add(a,b,c); } if(x==3) { a=read(); b=read(); c=0; add(a,b,c); add(b,a,c); } } for(int i=1;i<=n;i++) { add(0,i,0); dis[i]=-inf; } if(!spfa(0))printf("No "); else printf("Yes "); return 0; }
谢谢观看!!