OpenJ_Bailian - 3424 Candies (差分约束)

题面

During the kindergarten days, flymouse was the monitor of his class. Occasionally the head-teacher brought the kids of flymouse’s class a large bag of candies and had flymouse distribute them. All the kids loved candies very much and often compared the numbers of candies they got with others. A kid A could had the idea that though it might be the case that another kid B was better than him in some aspect and therefore had a reason for deserving more candies than he did, he should never get a certain number of candies fewer than B did no matter how many candies he actually got, otherwise he would feel dissatisfied and go to the head-teacher to complain about flymouse’s biased distribution.

飞鼠的幼儿园班上经常发糖果,全班Infinite个糖果由飞鼠分配给包括飞鼠(和史努比)在内的n个孩子。表现乖的人得到的糖果多很正常,但其中可能 有小孩A 觉得 无论自己的糖果多么少,另一个小孩B都不能得到 比自己多 超过c个的糖果。飞鼠不敢让同学们不满意,因为他们会告诉老师。

snoopy shared class with flymouse at that time. flymouse always compared the number of his candies with that of snoopy’s. He wanted to make the difference between the numbers as large as possible while keeping every kid satisfied. Now he had just got another bag of candies from the head-teacher, what was the largest difference he could make out of it?

史努比和飞鼠在同一个班上,飞鼠经常跟他攀比。飞鼠希望在自己不被告发的前提下,使自己得到比史努比尽量多的糖果,并央求你告诉他“飞鼠的糖果 - 史努比的糖果”数目的最大值。

Input

The input contains a single test cases. The test cases starts with a line with two integers N and M not exceeding 30 000 and 150 000 respectively. N is the number of kids in the class and the kids were numbered 1 through N. snoopy and flymouse were always numbered 1 and N. Then follow M lines each holding three integers AB and c in order, meaning that kid A believed that kid B should never get over c candies more than he did.

多组数据,输入到文件末尾

每组数据开头n和m,(m表示对糖果数的m对要求,飞鼠标号为n,史努比标号为1)

下面m行每行A、B、C,表示糖果数要满足“B的糖果数 ≤ A的糖果数 + C”

Output

Output one line with only the largest difference desired. The difference is guaranteed to be finite.

每组数据一行答案,保证有解。所有数都在int范围内。

题解

分析一下这道题的条件,设c[i]表示 i 的糖果数,发现“c[B] <= c[A] + C” 相似于 “dis[B] <= dis[A] + weight”,后者是一张图中每个点到原点最短路满足的条件,而且,每个点的最短路都是满足上述条件的最大值。于是,把A向B连一条边权为C的边,再从1到n跑一遍最短路就完了。(建议别用SPFA)

CODE(dij)

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#define MAXN 30005
#define MAXM 150005
#define LL long long
#define ENDL putchar('\n')
using namespace std;
LL read() {
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s == '-')f = -f;s = getchar();}
	while(s >= '0' && s <= '9') {x = x*10+(s-'0');s = getchar();}
	return f*x;
}
int n,m,i,j,s,o,k;
struct it{
	int v,w;
	it(){v = w = 0;}
	it(int V,int W){v = V;w = W;}
};
vector<it> g[MAXN];
LL dp[MAXN];
int bing(int a,int b) {return dp[a] < dp[b] ? a:b;}
int tre[MAXN<<2],M;
void maketree(int n) {M = 1;while(M < n+2)M <<= 1;}
void addtree(int x,int y) {
	int s = M + x;tre[s] = y;s >>= 1;
	while(s) {tre[s] = bing(tre[s<<1],tre[s<<1|1]);s >>= 1;}
}
int findall() {return tre[1];}
int main() {
	while(scanf("%d%d",&n,&m) == 2) {
		for(int i = 1;i <= m;i ++) {
			s = read();o = read();k = read();
			g[s].push_back(it(o,k));
		}
		memset(tre,0,sizeof(tre));
		maketree(n);
		for(int i = 0;i <= n;i ++) dp[i] = 1e18;
		dp[1] = 0;
		addtree(1,1);
		for(int i = 1;i <= n;i ++) {
			int t = findall();
			if(t == 0) break;
			for(int j = 0;j < g[t].size();j ++) {
				if(dp[g[t][j].v] > dp[t] + g[t][j].w) {
					dp[g[t][j].v] = dp[t] + g[t][j].w;
					addtree(g[t][j].v,g[t][j].v);
				}
			}
			addtree(t,0);
		}
		printf("%lld\n",dp[n]);
	}
	return 0;
}

 

posted @ 2020-10-03 20:41  DD_XYX  阅读(27)  评论(0编辑  收藏  举报