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 }