poj1201 Intervals(差分约束)

 差分约束第一题,差分约束就是解一系列的形如x1-x2<=(>=)a的不等式,由于移项之后为x1<=(>=)x2+a和最短路径的dist[i] <(>) dist[u] + mapp[u][i]联系 起来,故可以用最短路bellmanford和SPFA求解
显然dist[i]和dist[u]都为方程的解,根据大于或者小于可以以最短路径或者最长路径求解
我们举最短路径为例
因为是求的最短路径,那么结果可以保证dist[i] <= dist[u]+mapp[u][i],那么对此不等式移向可以得到dist[i] - dist[u] <= mapp[u][i],在最短路中,i,u分别为两个节点,而且存在一条u->i的路径。
现在回到POJ1201,输入样例如下:
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
设第i个点以前被选中的数有Si个,那么对于输入的一段闭区间[a, b]中有c[i]个数被选中,就有以下不等式方程:
(1)Sb[i] - Sa[i] >=  c[i];
(2)1 >= Si-S(i-1) >= 0;
由于我们是以最短路径为例,故将上述不等式改为
(1)Sa[i] - Sb[i] <=  -1*c[i];
(2)Si - S(i-1) <= 1;
(3)S(i-1) - S(i) <= 0;
据上述差分约束方程求解可以建图,对第一个输入,可以建图7->2,权值为-3,这样依次将全部输入建图,但是因为最后的结果可能是一个非连通图,所以还要根据上述不等式对每一个[i, i+1]建图,建图完后一次SPFA就可以求解
注意:最终答案是-dist[minn-1],最长路径则为dist[maxx+1];
附AC代码:
 (最短路径)

#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct node
{
       int num;
       int value;       
};
const int size = 51000;
bool inque[size];
int dist[size];
vector <node> mapp[size];
int minn, maxx;
void init()
{
     for (int i = 0; i < size; i ++){
         mapp[i].clear();    
     }     
}
void SPFA(int s1)
{
     queue <node> que;
     for (int i = minn; i <= maxx; i ++){
         inque[i] = false;
         dist[i] = 100000000;    
     }
     node s;
     s.num = s1;
     s.value = 0;
     que.push(s);
     dist[s.num] = 0;
     inque[s.num] = true;
     while (!que.empty()){
           node e = que.front();
           inque[e.num] = false;
           que.pop();
           for (int i = 0; i < mapp[e.num].size(); i ++){
               node ee = mapp[e.num][i];
               if (dist[ee.num] > dist[e.num] + ee.value){
                  dist[ee.num] = dist[e.num] + ee.value;
                  if (!inque[ee.num]){
                     ee.value = dist[ee.num];
                     que.push(ee);
                     inque[ee.num] = true;                    
                  }                   
               }    
           }      
     }         
}
int main()
{
    int n;
    while (scanf("%d", &n) != EOF){
          init();
          node a, b;
          minn = INT_MAX, maxx = -1;
          for (int i = 0; i < n; i ++){
              scanf("%d%d%d", &a.num, &b.num, &a.value);
              minn = minn > a.num? a.num : minn;
              maxx = maxx < b.num? b.num : maxx;
              a.num --;
              a.value*=-1;
              mapp[b.num].push_back(a);     
          }     
          for (int i = minn; i <= maxx; i ++){
              a.num = i,  a.value = 0;
              mapp[i+1].push_back(a);
              a.num = i+1,  a.value = 1;
              mapp[i].push_back(a);
          }
          SPFA(maxx);
          printf("%d\n", -dist[minn-1]);
    }
    return 0;    
}
/*(最长路径)*/

#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct node
{
       int num;
       int value;       
};
const int size = 51000;
bool inque[size];
int dist[size];
vector <node> mapp[size];
int minn, maxx;
void init()
{
     for (int i = 0; i < size; i ++){
         mapp[i].clear();    
     }     
}
void SPFA(int n, int s1)
{
     queue <node> que;
     for (int i = minn; i <= maxx; i ++){
         inque[i] = false;
         dist[i] = -100000000;    
     }
     node s;
     s.num = s1;
     s.value = 0;
     que.push(s);
     dist[s.num] = 0;
     inque[s.num] = true;
     while (!que.empty()){
           node e = que.front();
           inque[e.num] = false;
           que.pop();
           for (int i = 0; i < mapp[e.num].size(); i ++){
               node ee = mapp[e.num][i];
               if (dist[ee.num] < dist[e.num] + ee.value){
                  dist[ee.num] = dist[e.num] + ee.value;
                  if (!inque[ee.num]){
                     ee.value = dist[ee.num];
                     que.push(ee);
                     inque[ee.num] = true;                    
                  }                   
               }    
           }      
     }         
}
int main()
{
    int n;
    while (scanf("%d", &n) != EOF){
          init();
          node a, b;
          minn = INT_MAX, maxx = -1;
          for (int i = 0; i < n; i ++){
              scanf("%d%d%d", &a.num, &b.num, &b.value);
              minn = minn > a.num? a.num : minn;
              maxx = maxx < b.num? b.num : maxx;
              b.num ++;
              mapp[a.num].push_back(b);     
          }        
          for (int i = minn; i <= maxx; i ++){
              a.num = i+1,  a.value = 0;
              mapp[i].push_back(a);
              a.num = i,  a.value = -1;
              mapp[i+1].push_back(a);
          }
          SPFA(maxx, minn);
          printf("%d\n", dist[maxx+1]);
    }
    return 0;    
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值