poj 2983(差分约束)

来源:互联网 发布:转基因知乎 编辑:程序博客网 时间:2024/04/30 01:03
排位赛的E题,纠结了好久,做的时候猜到就是用差分约束来做。
对于每个防御点作为一个点,
(1)由P条件可以知, a - b = c(随便假设个方向),化成不等式组得{a - b >= c && a - b <= c} ,在移向得{b - a <= -c && a - b <= c} (建边a ->b, len = -c & b->a, len=c)
(2)由V条件可知,a - b >= 1 即 b - a <= -1 (建边 a -> b, 长度为-1)
根据以上构图,注意,如果用SPFA做的话,必须加一个超级源点,令它到每个点距离<=0就好,然后该怎么做就怎么做,存在负环表示无解,否则存在正解。
如果不加源点的话可以用Bellman_ford()做,否则有些不在统一图上的点是搜不到的

转:对于差分约束系统的一个资料参考:
1) 建图后求最短路(对应 <= 的差分约束)
从求最短路后分析开始。求最短路后一定有:d(u) + w(u,v) >= d(v) 转换为:d(v) – d(u) <= w(u,v)。然后这个式子与我们差分约束条件得到的不等式( X(a) - X(b) <= c )相似。
所以得到建图的规则为:一条b到a的边权值为c。
建图后求最短路即为一组解。
2) 建图后求最长路(对应 >= 的差分约束)
同上。求最长路后一定得到:d(u) + w(u,v) <= d(v) 转换为:d(v)-d(u)>=w(u,v)。然后对比差分约束条件的不等式( X(a) - X(b) >= c )。
所以得到建图的规则为:一条b到a的边权值为c。
建图后求最长路即为一组解。
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int INF=999999;
struct node
{
    int v;
    int len;
};
int n,m;
vector<node>map[1002];


int spfa()
{
  int vis[1009];
  memset(vis,0,sizeof(vis));
  int inq[1001];
  memset(inq,0,sizeof(inq));


  int dist[10001];
  queue<int>Q;
  for(int i=0;i<=n;i++)
  dist[i]=INF;
    while (!Q.empty())
    dist[0]=INF;
   Q.push(0);


  vis[0]=1;
  Q.push(0);
  while(!Q.empty())
  {
      int top=Q.front();
      Q.pop();
      inq[top]=0;
      for(int i=0;i<map[top].size();i++)
      {
          if(dist[map[top][i].v]>dist[top]+map[top][i].len)
          {
             dist[map[top][i].v]=dist[top]+map[top][i].len;
             if(!inq[map[top][i].v])
             {
                Q.push(map[top][i].v);
                inq[map[top][i].v]=1;
             }
             if(++vis[map[top][i].v]>=n)
             return 0;
          }
      }
  }
  return 1;
}


int main()
{
 while(cin>>n>>m)
 {
  for(int i=0;i<=n;i++)
  map[i].clear();
  char f;
  int u,v,c;
  for(int i=0;i<m;i++)
  {
    cin>>f;
    if(f=='P')
    {
        cin>>u>>v>>c;
        node tmp;
        tmp.len=c;
        tmp.v=u;
        map[v].push_back(tmp);


        tmp.len=-c;
        tmp.v=v;
        map[u].push_back(tmp);
    }
    else
    {
        cin>>u>>v;
        node t;
        t.len=-1;
        t.v=v;
        map[u].push_back(t);
    }
  }
  
  for (int i=0; i<=n; i++)
  {
      node k;
      k.v=i;
      k.len=0;
      map[0].push_back(k);
  }


    if(spfa())
    cout<<"Unreliable"<<endl;
    else
    cout<<"Reliable"<<endl;
 }
    return 0;
}


原创粉丝点击