【bzoj 2330】[SCOI2011]糖果 差分约束

236 篇文章 0 订阅

连差分约束不知道是什么的:http://www.cnblogs.com/void/archive/2011/08/26/2153928.html

假设 需要满足条件:

b-a<=k1     (1)

c-b<=k2     (2)

c-a<=k3     (3)

(1)(2)相加 得到不等式c-a<=k1+k2

所以要使条件满足的首要条件就是c-a<=min(k1+k2,k3) 但是可能题目中会有多个条件,不过本质并不会改变,依旧是求最小值,那么我们将a,b,c为点,以k为边权建边,得到一个有向图,求最短路就得到了min;

注意:1.最少每个人分到一个糖果从0填边的时候边权为1,而且要从后面向前填边

            2.最终ans用long long存

#include<cstdio>
#include<cstring>
#define maxn 100020
#include<iostream>
#include<queue>
#define LL long long
using namespace std;
queue<int >q;
int n,m,head[maxn*2],tot,vis[maxn],dis[maxn],times[maxn];
struct edge{
	int v,w,next;
}e[maxn*4];
void adde(int a,int b,int c){e[tot].v=b,e[tot].w=c,e[tot].next=head[a];head[a]=tot++;}

bool spfa(){
	q.push(0),dis[0]=0,times[0]=1;
	while(!q.empty()){
		int u=q.front();q.pop() ;
		vis[u]=0;
		for(int i=head[u];i!=-1;i=e[i].next ){
			int v=e[i].v ,w=e[i].w;
			if(dis[v]<dis[u]+w){
				dis[v]=dis[u]+w;
				times[v]++;
				if(times[v]>=n)return false;
				if(!vis[v]){
					vis[v]=1;
					q.push(v); 
				}
			}
		}
	}
	return true;
}

int main(){
	memset(head,-1,sizeof(head));
	scanf("%d%d",&n,&m);
	for(int pos,b,a,i=1;i<=m;i++){
		scanf("%d%d%d",&pos,&a,&b);
		if(pos==1){adde(a,b,0),adde(b,a,0);}
		else if(pos==2){
			if(a==b){printf("-1");}
			 adde(a,b,1);
		}else if(pos==3){
			adde(b,a,0);
		}else if(pos==4){
			if(a==b){printf("-1");return 0;}
			adde(b,a,1);break;
		}else if(pos==5){
			adde(a,b,0);
		}	
	}
	for(int i=n;i>=1;i--)adde(0,i,1);
	if(!spfa()){printf("-1");return 0;}
	LL ans=0;
	for(int i=1;i<=n;i++)
		ans+=(LL)dis[i];
	printf("%lld",ans);
	return 0;
}/*
5 7
1 1 2
2 3 2
4 4 1
3 4 5
5 4 5
2 3 5
4 5 1
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值