bzoj1731 [Usaco2005 dec]Layout 排队布局

传送门

分析

我们发现这两类关系可以写成b-a<=L和b-a>=D两种形式,所以我们可以得到这两种的连边策略分别是a向b连一条权值为L的边和b向a连一条权值为-D的边。然后我们跑最短路即可。注意要单独判一下负环。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int inf = 0x3f3f3f3f;
vector<pair<int,int> >v[11000];
int d[11000];
int main(){
      int n,m1,m2,i,j,k;
      scanf("%d%d%d",&n,&m1,&m2);
      for(i=1;i<=m1;i++){
          int x,y,z;
          scanf("%d%d%d",&x,&y,&z);
          v[x].push_back(make_pair(y,z));
      }
      for(i=1;i<=m2;i++){
          int x,y,z;
          scanf("%d%d%d",&x,&y,&z);
          v[y].push_back(make_pair(x,-z));
      }
      memset(d,0x3f,sizeof(d));
      d[1]=0;
      for(int _=1;_<=n;_++)
        for(int x=1;x<=n;x++)
          for(i=0;i<v[x].size();i++){
              int y=v[x][i].first,z=v[x][i].second;
              d[y]=min(d[y],d[x]+z);
          }
      for(int x=1;x<=n;x++)
          for(i=0;i<v[x].size();i++){
              int y=v[x][i].first,z=v[x][i].second;
              if(d[y]>d[x]+z){
                puts("-1");
                return 0;
              }
          }
      if(d[n]>=inf)puts("-2");
        else cout<<d[n]<<endl;
      return 0;
}
posted @ 2018-08-21 22:02  水题收割者  阅读(172)  评论(0编辑  收藏  举报