正文

Zju 2770 Burn the Linked Camp(2)2006-12-11 21:43:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/cruxd/21494.html

分享到:

    正如上文所言,图论的「精髓」就在「转化」了。把一个纯粹的数学问题转换成为可以用图表示的问题,然后通过求解路径(最小值?最大值?),得解。听起来很美。     以本题为例。给出每个军营的最大容量,给出从军营i到军营j最少的人数,求总人数的最小值。     这就是典型的差分约束了。有“分”,有“约束”,至于为什么叫“差”,我想大致是因为首先把Ai + .... + Aj写成S[j] - S[i - 1](和之差)的形式吧。btw,这种转换似乎是很常见的处理方法。     好吧,看上去和图论八竿子搭不上边。以题目给的第一组数据为例。 3 21000 2000 10001 2 11002 3 1300     我们可以得到如下关系式。(= 省略,下同)     A1 < 1000, A2 < 2000, A3 < 1000;       S2 - S0 > 1100, S3 - S1 > 1300;     第一组不等式又可写作     S1 - S0 < 1000, S2 - S1 < 2000, S3 - S2 < 1000     好吧.....不很明显,再改一下:     S0 - S1 > -1000, S1 - S2 > -2000, S2 - S3 > -1000     全部改成>后,回到上文中最后一个结论Distance(v) < Distance(u) + w(u,v)。即D(u) - D(v) > -w(u,v)。 把D改成S,是不是很像?......很牵强吧。     但毕竟还是有相同的地方。比如离散数学里的传递性:S0 - S1 > -1000, S1 - S2 > -2000, 那么,S0 - S2 > -3000。这就和图的路径奇妙地构成映射了。把每个S看作一个点,从前者向后者引出一条边,以差为负权值(-w(u,v))。这就是图了。     现在我们就有了一组已知量(5条边)-w(u, v),一组未知量 D0,D1,D2,3个点。这里Di代表的是点i到点3的距离....我的写法总是和标准差那么一点,更规范的写法是到点0的距离。显然,D3为0。这样就转化成了已知边求最短路径(S3-S0)。     回到问题。现在有五组不等式,要求的是在满足不等式的前提下S3 - S0的最小值。所谓最小值,其实所有满足不等式的D3的最大值;由于边为负,恰巧变成了最短路径。     当然这只会WA。刘备的兵营没有出现幽灵事件,Ai > 0。而且i到j是有上限的,不能比所有Ai到Aj的和更多。所以刚好是两组对称的不等式。世界是平衡的,不会有绝对的善和恶。     代码不是很长,大概是Bellman很偷懒的缘故。  #include <cstdio>#include <string> #define mx 9999999 int n, m, a[1001], ei, c[1001], d[1001]; struct Edge{ int u, v, w;} edge[23000]; void init(){ ei = 0; int i; for(i = 0; i <= n; i ++)  a[i] = mx; d[0] = 0; a[n] = 0;} bool bellman_ford(){ int i, k, t; for(i = 0; i < n; i ++) {    for(k = 0; k < ei; k ++)  {   t = a[edge[k].u] + edge[k].w;   if(a[edge[k].u] != mx && t < a[edge[k].v])   {    a[edge[k].v] = t;   }  }  //pa(); } for(k = 0; k < ei; k ++) {  if(a[edge[k].u] != mx && a[edge[k].u] + edge[k].w < a[edge[k].v])  {   return false;  } } return true;} int main(){ //freopen("in.txt", "r", stdin); while(scanf("%d %d", &n, &m) != EOF) {  init();  int i, u, v, w;  for(i = 1; i <= n; i ++)  {   scanf("%d", &c[i]);   edge[ei].u = i - 1;   //out   edge[ei].v = i;    //in   edge[ei].w = c[i];   ei ++;   edge[ei].u = i;   edge[ei].v = i - 1;   edge[ei].w = 0;   ei ++;   d[i] = c[i] + d[i - 1];  }  for(i = 0; i < m; i ++)  {   scanf("%d %d %d", &u, &v, &w);   //f(k) - f(t - 1) >= -j   edge[ei].u = v;   edge[ei].v = u - 1;   edge[ei].w = -w;   ei ++;   //f(k) - f(t - 1) <= c[t] + ... + c[k] == (d[k] - d[t - 1])   edge[ei].u = u - 1;   edge[ei].v = v;   edge[ei].w = d[v] - d[u - 1];   ei ++;  }  //pe();  if(!bellman_ford())   printf("Bad Estimations\n");  else   printf("%d\n", a[n] - a[0]); } return 0;}  

阅读(3529) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册