poj 1201(and)1716 (差分约束系统的建立和求解--其实也是spfa)

        这题好。

        题意:给n个区间中至少需要取Ci个数。求出满足n个条件的集合C的最少的元素个数.

转载结题报告:

        题目中的条件可以表示成S[bi+1]>=S[ai]+Ci//至少要Ci个。

       这与spfa中的松弛操作时很像的。因此可以看成一些点有D[v]>=D[u]+w(u,v)上式对任何u成立,所以v应该是里面最大的,若D[v]<D[u]+w(u,v)则D[v]=D[u]+w(u,v)于是。可以从ai和bi+1连一条线,它的长度是ci。

        这里只有这些条件还是不够的,还要加上两个使其满足整数性质条件1>=s[i+1]-s[i]>=0有了这么多条件,使其自然构成了一个差分约束系统。用spfa算法得到一个最长路,第一个到最后一个节点的最长路即是需要求的值。

      根据条件:1>=s[i+1]-s[i]>=0.在i和i+1建立权值为0,i和i-1建立权值为-1;

#include <iostream>
#include <queue>
#include <set>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;


const int INF=99999999;
struct node
{
   int v;
   int w;
};


int n;
vector<node>vv[50001];//存储有向和无向图的比较方便的方法
int dist[50001];


int MIN=500090;
int MAX=-1;
int vis[50003];


void spfa()//模型就是以MIN位原点的最长路
{
  memset(vis,0,sizeof(vis));
  queue<int>qu;
  vis[MIN]=1;
  dist[MIN]=0;
  qu.push(MIN);
  while(!qu.empty())
  {
      int top=qu.front();
      qu.pop();
      vis[top]=0;
      for(int i=0;i<vv[top].size();i++)
      {
          if(dist[vv[top][i].v]<dist[top]+vv[top][i].w)//松弛
          {
              dist[vv[top][i].v]=dist[top]+vv[top][i].w;
              if(!vis[vv[top][i].v])
              {
                      vis[vv[top][i].v]=1;
                      qu.push(vv[top][i].v);
              }
          }
      }
  }
}


int main()
{
    scanf("%d",&n);
    int u,v,c;
    node newone;


    for(int i=0;i<n;i++)
    {
      scanf("%d%d",&u,&v);
      v++;
      MIN=min(MIN,u);
      MAX=max(MAX,v);
      newone.v=v;
      newone.w=2;
      vv[u].push_back(newone);
    }


    for(int i=MIN;i<=MAX;i++)
    {
        node tmp;
        tmp.v=i+1;
        tmp.w=0;
        vv[i].push_back(tmp);


        tmp.v=i;
        tmp.w=-1;
        vv[i+1].push_back(tmp);
    }


    for(int i=MIN;i<=MAX;i++)
    {
        dist[i]=-INF;//求最长路嘛,就是初始化无穷小的
    }
    spfa();
    cout<<dist[MAX]<<endl;
    return 0;
}

你可能感兴趣的:(poj 1201(and)1716 (差分约束系统的建立和求解--其实也是spfa))