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 }

 

posted @ 2013-02-20 20:39  Missa  阅读(307)  评论(0编辑  收藏  举报