【BZOJ】【P2330】【SCOI2009】【糖果】【题解】【差分约束系统】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2330

一直以为差分约束系统很神……然后学了它……

求最大值跑最短路,求最小值跑最长路(我也不知道为什么)

如果有x-y>=z  连边 y->x  w = z (最长路)  x->y w=-z (最短路)

超级源点连所有点w=0,这道题似乎是说每个人至少有一个糖果……所以此题源点的dis值是1

Code:

#include<cstdio>
#include<cmath>
#include<vector>
#include<climits>
#include<queue>
#include<stack>
#include<cstring>
#include<iostream>
#include<algorithm>
#define V first
#define W second
using namespace std;
const int maxn=1e5+10;
typedef long long lld;
typedef pair<lld,lld> pii;
namespace TOPL{
	vector<pii>G[maxn];
	lld d[maxn];
	lld in[maxn],vis[maxn];
	void add(lld u,lld v,lld w){
		G[u].push_back(pii(v,w));
	}lld n,m;
	void init(){
		scanf("%lld%lld",&n,&m);
		for(lld i=1;i<=m;i++){
			lld opt;scanf("%lld",&opt);
			lld x,y;scanf("%lld%lld",&x,&y);
			switch(opt){
				case 1:{
					add(x,y,0);
					add(y,x,0);
					break;
				}
				case 2:{
					add(x,y,1);
					break;
				}
				case 3:{
					add(y,x,0);
					break;
				}
				case 4:{
					add(y,x,1);
					break;
				}
				case 5:{
					add(x,y,0);
					break;
				}
			}
		}
		for(lld i=1;i<=n;i++)
				add(0,i,0);
				
	}
	lld solve(){
		init();
		queue<lld>q;
		memset(d,0xaf,sizeof(d));
		d[0]=1;
		q.push(0);
		while(!q.empty()){
			lld u=q.front();q.pop();vis[u]=0;
			for(lld i=0;i<G[u].size();i++){
				lld v=G[u][i].V,w=G[u][i].W;
				if(d[v]<d[u]+w){
					d[v]=d[u]+w;
					if(!vis[v]){
						vis[v]=1;
						q.push(v);
						in[v]++;
						if(in[v]>=100){
							puts("-1");
							return 0;
						}
					}
				}
			}
		}
		lld ans=0;
		for(int i=1;i<=n;i++)
			ans+=d[i];
		cout<<ans<<endl;
		return 0;
	}
}
int main(){
//	freopen("candy5.in","r",stdin);
	return TOPL::solve();	
}





你可能感兴趣的:(bzoj,省选)