洛谷 P3275(差分约束系统)

P3275

(1)思路:

因为询问最少有多少个糖果,所以可以将老师设为一个源点,想同学们分发糖果,

因为“至少”,所以建图,求最长路之和,

要保证所有小朋友都分到糖果,所以一开始老师最少给学生1个糖果。

如果图中存在环这整情况就不成立。

(2)注意:

一、x = 2,x = 4的中出现x == y 时,会出现环,所以直接就不成立。

二、用数组模拟队列会更快,这里不能用堆栈(之前看矿斌的博客说堆栈可以加快最短路的速度,

但是这道题目不适用)。

三、注意结果用long long。

(3)代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL maxn = 2e5+10;
const LL INF = 1e9+10;
LL head[maxn],vis[maxn],dis[maxn],tim[maxn],tot,n,m,st[maxn<<2];
LL ans;
struct Node{
	LL v,nxt,w;
}cur[maxn<<2];
void Init(){
	memset(head,-1,sizeof(head));
	tot = 0;
} 
void Add(LL x,LL y,LL z){
	cur[tot] = Node{y,head[x],z};
	head[x] = tot++;
}
bool spfa(){
	for(LL i=0;i<=n;i++){
		dis[i] = -INF;vis[i] = 0;tim[i] = 0;
	}
	LL top = 0,rear = 0;
	st[rear++] = 0;dis[0] = 0;tim[0]++;
	while(top<rear){
		LL x = st[top++];vis[x] = 0;
		for(LL i=head[x];i!=-1;i=cur[i].nxt){
			LL y = cur[i].v;
			if(dis[y]<dis[x]+cur[i].w){
				dis[y] = dis[x]+cur[i].w;
				if(vis[y]==0){
					vis[y] = 1;
					if(++tim[y]>n) return false;
					st[rear++] = y;
				}
			}
		}
	}
	ans = 0;
	for(LL i=1;i<=n;i++)
	ans += dis[i];
	
	return true;
}
inline void read(LL &x){
	x = 0; char ch = getchar();
	while (!isdigit(ch)) ch = getchar();
	while (isdigit(ch)) x = (x * 10) + (ch & 15), ch = getchar();
}
int main(void){
	Init();
	read(n);read(m);
	for(LL i=0;i<m;i++){
		LL op,x,y;
		read(op);read(x);read(y); 
		if(op==1){
			Add(x,y,0);Add(y,x,0);
		}
		else if(op==2){
			if(x==y){
				printf("-1\n");
				return 0;
			}
			Add(x,y,1);
		}
		else if(op==3){
			Add(y,x,0);
		}
		else if(op==4){
			if(x==y){
				printf("-1\n");
				return 0;
			}
			Add(y,x,1);
		}
		else if(op==5){
			Add(x,y,0);
		}
	}
	for(LL i=n;i>=1;i--) Add(0,i,1);
	if(spfa()==false){
		printf("-1\n");
		return 0;
	}
	printf("%lld\n",ans);
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/91874269
今日推荐