poj 1201/zoj 1508(差分约束)

以前用线段树做过这题。

dis[i]表示从0->i-1这i个数存在多少个数。

则有dis[b+1]-dis[a]>=c;

dis[i+1]-dis[i]>=0 && dis[i+1]-dis[i]<=1

转换成为:

dis[a]-dis[b+1]<=-c;

dis[i]-dis[i+1]<=0 

dis[i+1]-dis[i]<=1

建图。dis[en]-dis[st]<=w.

View Code
 1 // File Name: 1508.cpp
 2 // Author: Missa
 3 // Created Time: 2013/2/20 星期三 0:41:05
 4 
 5 #include<iostream>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<algorithm>
 9 #include<cmath>
10 #include<queue>
11 #include<stack>
12 #include<string>
13 #include<vector>
14 #include<cstdlib>
15 #include<map>
16 #include<set>
17 using namespace std;
18 #define CL(x,v) memset(x,v,sizeof(x));
19 
20 const int maxn = 5e4+5;
21 const int maxm = 2e5+5;
22 const int inf = 0x3f3f3f3f;
23 struct edge
24 {
25     int v,c,next;
26 }p[maxm];
27 int n,m,dis[maxn],e,head[maxn];
28 int mmin,mmax;
29 void addedge(int u,int v,int c)
30 {
31     p[e].v=v;p[e].c=c;
32     p[e].next=head[u];head[u]=e++;
33 }
34 bool relax(int u,int v,int c)
35 {
36     if(dis[v]>dis[u]+c)
37     {
38         dis[v]=dis[u]+c;
39         return true;
40     }
41     return false;
42 }
43 void init()
44 {
45     CL(head,-1);
46     e=0;
47     mmin=inf;mmax=-1;
48     for(int i=0;i<m;i++)
49     {
50         int u,v,c;
51         scanf("%d%d%d",&u,&v,&c);
52         addedge(v+1,u,-c);
53         if(mmin>u) mmin=u;
54         if(mmax<v) mmax=v;
55     }
56     for(int i=mmin;i<mmax+1;i++)
57     {
58         addedge(i+1,i,0);
59         addedge(i,i+1,1);
60     }
61 }
62 int spfa(int src)
63 {
64     bool vis[maxn];CL(vis,0);
65     CL(dis,0x3f);
66     dis[src]=0;vis[src]=1;
67     queue<int>q;q.push(src);
68     while(!q.empty())
69     {
70         int pre=q.front();q.pop();
71         vis[pre]=0;
72         for(int i=head[pre];i+1;i=p[i].next)
73         {
74             if(relax(pre,p[i].v,p[i].c) && !vis[p[i].v])
75             {
76                 q.push(p[i].v);
77                 vis[p[i].v]=1;
78             }
79         }
80     }
81     return -(dis[mmin]-dis[mmax+1]);
82 }
83 int main()
84 {
85     while(~scanf("%d",&m))
86     {
87         init();
88         //cout<<mmin<<" "<<mmax<<endl;
89         printf("%d\n",spfa(mmax+1));
90     }
91     return 0;
92 }
原文地址:https://www.cnblogs.com/Missa/p/2917970.html