zoj 3668 (差分约束)

约束条件 :f[i]  表示前i块石头的能量总和。

f[R]-f[L-1]>=A  

f[R]-f[L-1]<=B

f[i]-f[i-1]<=10000

f[i]-f[i-1]>=-10000

关于为什么是字典序。。。在网上看到如下:

总结了一下,差分约束系统有两个解决方案:

1, 最短路模型。 所有的约束条件都是形如f(X)<=f(Y)+B,B正负不分。这样在有向图中addEdge(Y, X, B)这条边,这样根据最短路求解的性质我们可以得到X的最短路值满足了所有的f(X)<=f(Yi)+Bi,并且使得某个(某些)f(X)=f(Yk)+Bk。本来是f(X)<=f(Yk)+Bk的,现在都f(X)=f(Yk)+Bk了,因此利用最短路模型求出来的f值是最大值。

2,最长路模型。所有的约束条件都是形如f(X)>=f(Y)+B,B正负不分。这样在有向图中addEdge(Y, X, B)这条边,这样根据最长路求解的性质我们可以得到X的最长路值满足了所有的f(X)>=f(Yi)+Bi,并且使得某个(某些)f(X)=f(Yk)+Bk。本来是f(X)>=f(Yk)+Bk的,现在只是f(X)=f(Yk)+Bk了,因此利用最长路模型求出来的f值是最小值。

回归到本题,所有值求是最大值,sum[0]和sum[n]确定的,于是可以得到是字典序最大。

ps:开始写完后试着交了下。。。没想到ac了。。

View Code
 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<cmath>

 6 #include<queue>

 7 #include<stack>

 8 #include<string>

 9 #include<vector>

10 #include<cstdlib>

11 #include<map>

12 #include<set>

13 using namespace std;

14 #define CL(x,v) memset(x,v,sizeof(x));

15 const int inf = 0x3f3f3f3f;

16 const int maxm = 2e5+5;

17 const int maxn = 1005;

18 int n,m;

19 struct edge

20 {

21     int v;

22     int c;

23     edge(){}

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

25 };

26 vector<edge>e[maxn];

27 int dis[maxn],cnt[maxn];

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

29 {

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

31 }

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

33 {

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

35     {

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

37         return true;

38     }

39     return false;

40 }

41 bool spfa(int src)

42 {

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

44     CL(dis,0x3f);

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

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

47     while(!q.empty())

48     {

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

50         vis[pre]=0;

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

52         {

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

54             {

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

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

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

58             }

59         }

60     }

61     return true;

62 }

63 int main()

64 {

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

66     {

67         CL(cnt,0);

68         CL(e,0);

69         int u,v,c,d;

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

71         {

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

73             u--;

74             addedge(u,v,d);

75             addedge(v,u,-c);

76         }

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

78         {

79             addedge(i-1,i,10000);

80             addedge(i,i-1,10000);

81         }

82         if(!spfa(0)) puts("The spacecraft is broken!");

83         else

84         {

85             //cout<<dis[1]<<" "<<dis[2]<<endl;

86             printf("%d",dis[1]-dis[0]);

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

88                 printf(" %d",dis[i]-dis[i-1]);

89             printf("\n");

90         }

91     }

92     return 0;

93 }

 

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