(差分约束)洛谷 P1993 小K的农场

这应该算是一道比较水的差分约束题了(不过为啥不开o2炸了啊)

我这是最大值写法

操作1:a到b连一条值为-c的有向边

操作2:b到a连一条值为c的有向边

操作3:a到b连一条值为0的双向边

题目描述

小 K 在 MC 里面建立很多很多的农场,总共 nnn 个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共 mmm 个),以下列三种形式描述:

  • 农场 aaa 比农场 bbb 至少多种植了 ccc 个单位的作物;
  • 农场 aaa 比农场 bbb 至多多种植了 ccc 个单位的作物;
  • 农场 aaa 与农场 bbb 种植的作物数一样多。

但是,由于小 K 的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。

输入格式

第一行包括两个整数 nnn 和 mmm,分别表示农场数目和小 K 记忆中的信息数目。

接下来 mmm 行:

  • 如果每行的第一个数是 111,接下来有三个整数 a,b,ca,b,ca,b,c,表示农场 aaa 比农场 bbb 至少多种植了 ccc 个单位的作物;
  • 如果每行的第一个数是 222,接下来有三个整数 a,b,ca,b,ca,b,c,表示农场 aaa 比农场 bbb 至多多种植了 ccc 个单位的作物;
  • 如果每行的第一个数是 333,接下来有两个整数 a,ba,ba,b,表示农场 aaa 种植的的数量和 bbb 一样多。

输出格式

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

输入输出样例

输入 #1

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

输出 #1

Yes

说明/提示

数据规模与约定

对于 100%100\%100% 的数据,保证 1≤n,m,a,b,c≤100001 \le n,m,a,b,c \le 100001≤n,m,a,b,c≤10000

#include<cstdio>
#include<cstring>
#include<queue>
#define MAX 300000
#define INF 0x3f3f3f
using namespace std;

struct Edge{
	int from,to,vel,next;
};
Edge edge[MAX];
int head[MAX];
int dist[MAX],vis[MAX];
int used[MAX];
int n,m,w,cnt;
void addedge(int u,int v,int w)
{
	Edge E={u,v,w,head[u]};
	edge[cnt]=E;
	head[u]=cnt++;
}

int SPFA(int t)
{
	queue<int>Q;
	memset(dist,INF,sizeof(dist));
	memset(vis,0,sizeof(vis));
	memset(used,0,sizeof(used));
	used[t]++;  // 记录元素 入队次数
	vis[t]=1;  // 起点从 1 开始
	dist[t]=0;
	Q.push(t);
	while(!Q.empty())
	{
		int u=Q.front();
		Q.pop();
		vis[u]=0;
		for(int i=head[u];i!=-1;i=edge[i].next)
		{
			int v=edge[i].to;
			if(dist[v]>dist[u]+edge[i].vel)
			{
				dist[v]=dist[u]+edge[i].vel;
				if(vis[v]==0)
				{
					used[v]++; // 每次进队 次数加 1
					if(used[v]>n) // 任意元素入队次数大于 N 说明有负环
						return 1;

					vis[v]=1;
					Q.push(v);
				}
			}
		}
	}
	return 0;
}

int main()
{
	int F,a,b,t;
	//scanf("%d",&F);
	F=1;
	while(F--)
	{
		memset(head,-1,sizeof(head));
		cnt=0;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) addedge(0,i,0);
		for(int i=1;i<=m;++i)
		{
		    int op;
		    scanf("%d",&op);
			//scanf("%d%d%d",&a,&b,&t);//s-e<=t
			if(op==1)
            {
                scanf("%d%d%d",&a,&b,&t);
                addedge(a,b,-t);
            }
            else if(op==2)
            {
                scanf("%d%d%d",&a,&b,&t);
                addedge(b,a,t);
            }
            else
            {
                scanf("%d%d",&a,&b);
                addedge(a,b,0);addedge(b,a,0);
            }
			//addedge(e,s,t);
		}
		if(SPFA(0)==0)
        {
            printf("Yes\n");
        }
		else
			printf("No\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43497140/article/details/107095281