差分超级坑题--nkoj2112(scoi2011)

Problem C:【SCOI2011 Day1】糖果

Time Limit:10000MS  Memory Limit:165536K
Total Submit:308 Accepted:74 
Case Time Limit:3000MS

Description

  幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。

Input

  输入的第一行是两个整数N,K。 
  接下来K行,表示这些点需要满足的关系,每行3个数字,X,A,B。 
  如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多; 
  如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果; 
  如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果; 
  如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果; 
  如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;

Output

  输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。

Sample Input

5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1

Sample Output

11

Hint

对于30%的数据,保证 N<=100 
对于100%的数据,保证 N<=100000 
对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N


注意使用long long

重要结论1:
以Xi-Xj<=C为约束条件,建图求最短路后得到的是最大解。
所有解都不大于且尽可能逼进Dis[X0]。


若有Xi-Xj<=C,可在图中连一条从Xj出发指向Xi的有向边,边的权值为C。再添加一个源点X0,从X0出发往X1,X2,...,Xn连一条权值为0的有向边。
然后以X0为起点,求单源最短路(无负权环),求出的起点X0到每个点的距离Dis[ ]就是不等式组的一组解。
若一开始就把Dis[X0]的值定死为A,再求最短路,那么求出的其它点的Dis[ ]值一定不会大于A。并且,求出的Dis[ ]是不大于A且与A最接近的一组。也就是所有点的Dis[ ]都达到了最大,也称为最大解。


若有Xi-Xj>=C,可在图中连一条从Xj出发指向Xi的有向边,边的权值为C。再添加一个源点X0,从X0出发往X1,X2,...,Xn连一条权值为0的有向边。


然后以X0为起点,求单源最长路(无正权环),求出的起点X0到每个点的距离Dis[ ]就是不等式组的一组解。


若一开始就把Dis[X0]的值定死为A,再求最长路,那么求出的其它点的Dis[ ]值一定不会小于A。并且,求出的Dis[ ]是不小于A且与A最接近的一组。也就是所有点的Dis[ ]都达到了最小,也称为最小解。


重要结论2:
以Xi-Xj>=C为约束条件,建图求最长路后得到的是最小解。
所有解都不小于且尽可能逼进Dis[X0]。

差分约束小结

最短路:(对应最大解)
1.按Xi-Xj<=C的条件建图(从Xj出发向Xi连接权值为C的有向边)。
2.添加超级源点X0,从X0出发往每个点连接一条权值为0的边
3.固定Dis[X0]的值为A
4.以X0为源点求最短路(无负权回路的前提下),求出的每个点的Dis[ ]对应一组解。
5.所有的Dis[ ]一定都是<=A的最大解。


最长路:(对应最小解)
1.按Xi-Xj>=C的条件建图(从Xj出发向Xi连接权值为C的有向边)。
2.添加超级源点X0,从X0出发往每个点连接一条权值为0的边
3.固定Dis[X0]的值为A
4.以X0为源点求最长路(无正权回路的前提下),求出的每个点的Dis[ ]对应一组解。
5.所有的Dis[ ]一定都是>=A的最小解。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
const int inf=-1e9;
using namespace std;
long long dis[1000005],next[4000005],last[1000005];
long long cnt[1000005];
bool vis[1000005];
long long m=0;
long long n,k;
queue<long long>q;
struct edge{
	long long from,to,len;
	edge(){}
	edge(long long a,long long b,long long c){from=a;to=b;len=c;}
};
edge line[4000005];
inline void read(long long &x){  
    char t;  
    bool mark=false;  
    for(;t=getchar(),t<'0'||t>'9';) if(t=='-') mark=1;  
    for(x=t-'0',t=getchar();'0'<=t&&t<='9';x=x*10+t-'0',t=getchar());  
    x=mark?-x:x;  
}
void add_edge(long long from,long long to,long long len){
	m++;
	next[m]=last[from];
	last[from]=m;
	line[m]=edge(from,to,len);
}
bool spfa(int s){
	long long i,j,k,t,ans=0;
	for(i=1;i<=n;i++)dis[i]=inf;
	vis[s]=true;
	dis[s]=1; 
	cnt[s]=1;
	q.push(s);
	while(q.size()){
		t=q.front();q.pop();vis[t]=false;
		for(i=last[t];i;i=next[i]){
			if(dis[line[i].to]<dis[line[i].from]+line[i].len){
				dis[line[i].to]=dis[line[i].from]+line[i].len;
				if(vis[line[i].to]==false){
					cnt[line[i].to]++;
					if(cnt[line[i].to]>=n){
						return false;
					}
					q.push(line[i].to);
					vis[line[i].to]=true;
				}
			}
		}
	}
	return true;
}
int main(){
	long long i,j,t,x,y,ans=0;
	cin>>n>>k;
	for(i=1;i<=k;i++){
		read(t);read(x);read(y);
		if(t==1){
			add_edge(x,y,0);
			add_edge(y,x,0);
		}
		else if(t==2){
			if(x==y){
				cout<<"-1";return 0;
			}
			add_edge(x,y,1);
		}
		else if(t==3){
			add_edge(y,x,0);
		}
		else if(t==4){
			if(x==y){
				cout<<"-1";return 0;
			}
			add_edge(y,x,1);
		}
		else{
			add_edge(x,y,0);
		}
	}
	for(i=n;i>=1;i--)add_edge(n+1,i,0);//数据有鬼,不能从1--n
	bool flag=spfa(n+1);
	if(flag){
		for(i=1;i<=n;i++)ans=ans+dis[i];
		cout<<ans;
	}
	else cout<<"-1";
	return 0;
} 


中描述了一个幼儿园里分配糖果的问,每个小朋友都有自己的要求。问的输入包括两个整数NN和KK,表示幼儿园里的小朋友数量和要满足的要求数量。接下来的KK行表示小朋友们的要求,每行有三个数字,XX,AA,BB。如果X=1,表示第AA个小朋友分到的糖果必须和第BB个小朋友分到的糖果一样多;如果X=2,表示第AA个小朋友分到的糖果必须少于第BB个小朋友分到的糖果;如果X=3,表示第AA个小朋友分到的糖果必须不少于第BB个小朋友分到的糖果;如果X=4,表示第AA个小朋友分到的糖果必须多于第BB个小朋友分到的糖果;如果X=5,表示第AA个小朋友分到的糖果必须不多于第BB个小朋友分到的糖果。这个问可以被看作是一个差分约束系统的问。 具体地说,可以使用差分约束系统来解决这个问差分约束系统是一种通过给变量之间的关系添加约束来求解最优解的方法。对于这个问,我们需要根据小朋友们的要求建立约束条件,并通过解决这个约束系统来得出最小的糖果数量。 在问的输入中,X的取值范围为1到5,分别对应不同的关系约束。根据这些约束,我们可以构建一个差分约束图。图中的节点表示小朋友,边表示糖果数量的关系。根据不同的X值,我们可以添加相应的边和权重。然后,我们可以使用SPFA算法(Shortest Path Faster Algorithm)来求解这个差分约束系统,找到满足所有约束的最小糖果数量。 需要注意的是,在读取输入时需要判断X和Y是否合法,即是否满足X≠Y。如果X=Y,则直接输出-1,因为这种情况下无法满足约束条件。 综上所述,为了满足每个小朋友的要求,并且满足所有的约束条件,我们可以使用差分约束系统和SPFA算法来求解这个问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【差分约束系统】【SCOI2011】糖果 candy](https://blog.youkuaiyun.com/jiangzh7/article/details/8872699)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [P3275 [SCOI2011]糖果(差分约束板子)](https://blog.youkuaiyun.com/qq_40619297/article/details/88678605)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值