<题目链接>
题目大意:
给n个人派糖果,给出m组数据,每组数据包含A,B,c 三个数,意思是A的糖果数比B少的个数不多于c,即B的糖果数 - A的糖果数<= c 。最后求n 比 1 最多多多少糖果。
解题分析:
这是一题典型的差分约束题。不妨将糖果数当作距离,把相差的最大糖果数看成有向边AB的权值,我们得到 dis[B]-dis[A]<=w(A,B)。看到这里,我们联想到求最短路时的松弛技术,即if(dis[B]>dis[A]+w(A,B), dis[B]=dis[A]+w(A,B)。即是满足题中的条件dis[B]-dis[A]<=w(A,B),由于要使dis[B] 最大,所以我们需要对每个点求最小值。
因为对于不同的不等式合并来说,一个数所能取得的最大值,不是看它小于等于的最大值,而是看它小于等于的最小值,即求出对该数约束最强的上界,放在本题,就是求最短路了。
//下面是普通最短路算法
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <queue> using namespace std; #define INF 0x3f3f3f3f const int N = 30000+100; const int M =150000+100; int n,m; int head[N],vis[N]; int cnt;
struct EDGE{ int to; int next; int w; }edge[M]; void init(){ memset(head,-1,sizeof(head)); cnt=0; } void add(int u,int v,int w){ edge[cnt].to=v,edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } struct NODE{ int loc; int dis; NODE(int a=0,int b=0):loc(a),dis(b){} bool operator < (const NODE &tmp)const{ return dis>tmp.dis; } }d[N]; void dij(int st){ for(int i=1;i<=n;i++){ vis[i]=0,d[i].loc=i,d[i].dis=INF; } priority_queue<NODE>q; d[st].dis=0; q.push(d[st]); while(!q.empty()){ NODE now=q.top(); q.pop(); if(vis[now.loc])continue; vis[now.loc]=1; for(int i=head[now.loc];i!=-1;i=edge[i].next){ int v=edge[i].to; if(d[v].dis>d[now.loc].dis+edge[i].w){ d[v].dis=d[now.loc].dis+edge[i].w; q.push(d[v]); } } } } int main(){ while(scanf("%d %d",&n,&m)!=EOF){ init(); for(int i=1;i<=m;i++){ int a,b,c; scanf("%d %d %d",&a,&b,&c); add(a,b,c); } dij(1); printf("%d ",d[n].dis); } return 0; }
2018-08-31