zoj 2770(差分约束)

设a[i] 为第i个营的人数,s[i] = a[1] + a[2] + … + a[i], s[0] = 0

       则对于题目

       Ci 有: 0 <= s[i] – s[i-1] <= a[i]  -----(1)

       i, j, k有:a[i]+a[i+1]+...a[j]>= s[j] – s[i-1] >= k   -----(2)

       化为以下四个式子:

s[i]-s[i-1]<=a[i]  ------>addedge(i-1,i,a[i])

s[i-1]-s[i]<=0 --------->addedge(i,i-1,0)

s[j]-s[i-1]<=sum[j]-sum[i-1]----->addedge(i-1,j,sum[j]-sum[i-1])

s[i-1]-s[j]<=-k  ---->addedge(j,i-1,-k)

设答案为ans.则显然s[n]-s[0]>=ans  ---->s[0]-s[n]<=-ans;

相当于从n-->0的边权值为-ans。

故可以从n为源点求最短路.

 

另外:用vector来存邻接表貌似很方便。。

 

 1 // File Name: 2770.cpp

 2 // Author: Missa

 3 // Created Time: 2013/2/20 星期三 12:22:46

 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 const int inf = 0x3f3f3f3f;

20 const int maxm = 2e5+5;

21 const int maxn = 1005;

22 int n,m;

23 struct edge

24 {

25     int v;

26     int c;

27     edge(){}

28     edge(int v,int c):v(v),c(c){}

29 };

30 vector<edge>e[maxn];

31 int a[maxn],sum[maxn],dis[maxn],cnt[maxn];

32 void addedge(int u,int v,int c)

33 {

34     e[u].push_back(edge(v,c));

35 }

36 bool relax(int u,int v,int c)

37 {

38     if(dis[v]>dis[u]+c)

39     {

40         dis[v]=dis[u]+c;

41         return true;

42     }

43     return false;

44 }

45 bool spfa(int src)

46 {

47     bool vis[maxn];CL(vis,0);

48     CL(dis,0x3f);

49     dis[src]=0;vis[src]=1;

50     queue<int>q;q.push(src);

51     while(!q.empty())

52     {

53         int pre=q.front();q.pop();

54         vis[pre]=0;

55         for(int i=0;i<e[pre].size();i++)

56         {

57             if(relax(pre,e[pre][i].v,e[pre][i].c) && !vis[e[pre][i].v])

58             {

59                 if((++cnt[e[pre][i].v]) > n) return false;

60                 q.push(e[pre][i].v);

61                 vis[e[pre][i].v]=1;

62             }

63         }

64     }

65     return true;

66 }

67 int main()

68 {

69     while(~scanf("%d%d",&n,&m))

70     {

71         CL(a,0);

72         CL(sum,0);

73         CL(cnt,0);

74         CL(e,0);

75         int u,v,c;

76         for(int i=1;i<=n;i++)

77         {

78             scanf("%d",&a[i]);

79             sum[i]=sum[i-1]+a[i];

80         }

81         for(int i=1;i<=m;i++)

82         {

83             scanf("%d%d%d",&u,&v,&c);

84             addedge(v,u-1,-c);

85             addedge(u-1,v,sum[v]-sum[u-1]);

86         }

87         for(int i=1;i<=n;i++)

88         {

89             addedge(i,i-1,0);

90             addedge(i-1,i,a[i]);

91         }

92         if(!spfa(n)) puts("Bad Estimations");

93         else

94             printf("%d\n",dis[n]-dis[0]);

95     }

96     return 0;

97 }

 

 

 

你可能感兴趣的:(差分约束)