[差分約束] Topcoder SRM553 Div1 Hard. YamanoteLine

可行的長度肯定是一個區間

約束條件可以建城差分約束系統,那麼判無解就是判是否有負環

記一下負環上關於總長度的係數,二分就可以了

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int N=1010;

typedef long long ll;

int n,t;

struct Edge{
  int s,t;
  ll k,d;
  Edge(){}
  Edge(int _s,int _t,ll _k,ll _d):s(_s),t(_t),k(_k),d(_d){}
}e[N];

ll dis[N],f[N];

inline pair<int,ll> check(ll x){
  for(int i=0;i<=n;i++) dis[i]=1LL<<60,f[i]=0;
  dis[0]=0;
  ll ret; bool flg;
  for(int i=1;i<=n*n;i++){
    flg=0;
    for(int i=1;i<=t;i++){
      if(dis[e[i].s]==(1LL<<60)) continue;
      if(dis[e[i].t]>dis[e[i].s]+x*e[i].k+e[i].d){
    dis[e[i].t]=dis[e[i].s]+x*e[i].k+e[i].d;
    f[e[i].t]=ret=f[e[i].s]+e[i].k;
    if(dis[e[i].t]<0) return make_pair(0,ret);
    flg=1;
      }
    }
  }
  if(!flg) return make_pair(1,0);
  else return make_pair(0,ret);
}

class YamanoteLine{
public:
  ll howMany(int _n, vector<int> s1, vector<int> t1, vector<int> l1, vector<int> s2, vector<int> t2, vector<int> l2){
    n=_n;
    for(int i=0;i<=n-1;i++) e[++t]=Edge(i+1,i,0,-1);
    for(int i=0;i<s1.size();i++){
      int S=s1[i],T=t1[i],L=l1[i];
      if(S<T) e[++t]=Edge(T,S,0,-L);
      else e[++t]=Edge(T,S,1,-L);
    }
    for(int i=0;i<s2.size();i++){
      int S=s2[i],T=t2[i],L=l2[i];
      if(S<T) e[++t]=Edge(S,T,0,L);
      else e[++t]=Edge(S,T,-1,L);
    }
    e[++t]=Edge(0,n,1,0);
    e[++t]=Edge(n,0,-1,0);
    ll U,D,L,R,mid;
    L=0; R=1LL<<60;
    while(L<=R){
      mid=L+R>>1;
      pair<int,ll> cur=check(mid);
      if(cur.first) D=mid;
      if(cur.second<0 || cur.first) R=mid-1;
      else L=mid+1;
    }
    L=0; R=1LL<<60;
    while(L<=R){
      mid=L+R>>1;
      pair<int,ll> cur=check(mid);
      if(cur.first) U=mid;
      if(cur.second>0 || cur.first) L=mid+1;
      else R=mid-1;
    }
    if(U==(1LL<<60)) return -1;
    return max(U-D+1,0LL);
  }

};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章