可行的长度肯定是一个区间
约束条件可以建城差分约束系统,那么判无解就是判是否有负环
记一下负环上关于总长度的系数,二分就可以了
#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);
}
};