题意:给定一个长为n的序列,每个位置可以选择取或不取,要求构造方案使得:
1.对于前M1个约束,区间【L,R】内取的数量必须严格不少于K
2.对于后M2个约束,区间【L,R】外取的数量必须严格不少于K
3.满足所有M1+M2个约束的前提下使得取的个数最少,输出最少取的个数
n,M1,M2<=3e3
思路:做法一:
特殊的SPFA判负环的技巧见https://www.cnblogs.com/myx12345/p/6212893.html
大致说来就是用栈和初始置0两个地方
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef long double ld; 7 typedef pair<int,int> PII; 8 typedef pair<ll,ll> Pll; 9 typedef vector<int> VI; 10 typedef vector<PII> VII; 11 typedef pair<ll,ll>P; 12 #define N 500010 13 #define M 1000000 14 #define INF 1e9 15 #define fi first 16 #define se second 17 #define MP make_pair 18 #define pb push_back 19 #define pi acos(-1) 20 #define mem(a,b) memset(a,b,sizeof(a)) 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 23 #define lowbit(x) x&(-x) 24 #define Rand (rand()*(1<<16)+rand()) 25 #define id(x) ((x)<=B?(x):m-n/(x)+1) 26 #define ls p<<1 27 #define rs p<<1|1 28 #define fors(i) for(auto i:e[x]) if(i!=p) 29 30 const int MOD=1e9+7,inv2=(MOD+1)/2; 31 double eps=1e-6; 32 int dx[4]={-1,1,0,0}; 33 int dy[4]={0,0,-1,1}; 34 35 struct edge 36 { 37 int x,y,z; 38 }a[N],b[N]; 39 40 int head[N],vet[N],nxt[N],inq[N],dis[N],stk[N],len[N],t[N], 41 n,m1,m2,tot; 42 43 int read() 44 { 45 int v=0,f=1; 46 char c=getchar(); 47 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 48 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 49 return v*f; 50 } 51 52 ll readll() 53 { 54 ll v=0,f=1; 55 char c=getchar(); 56 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 57 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 58 return v*f; 59 } 60 61 void add(int a,int b,int c) 62 { 63 nxt[++tot]=head[a]; 64 vet[tot]=b; 65 len[tot]=c; 66 head[a]=tot; 67 } 68 69 void build(int k) 70 { 71 //printf("k=%d ",k); 72 tot=0; 73 rep(i,0,n) head[i]=0; 74 rep(i,0,n-1) 75 { 76 add(i+1,i,0); 77 add(i,i+1,1); 78 } 79 rep(i,1,m1) add(a[i].y,a[i].x-1,-a[i].z); 80 rep(i,1,m2) add(b[i].x-1,b[i].y,k-b[i].z); 81 add(0,n,k); 82 add(n,0,-k); 83 } 84 85 int isok() 86 { 87 rep(i,0,n) inq[i]=dis[i]=t[i]=0; 88 int top=0; 89 rep(i,0,n) 90 { 91 top++; 92 stk[top]=i; 93 inq[i]=1; 94 t[0]=i; 95 } 96 while(top) 97 { 98 int u=stk[top]; 99 top--; 100 inq[u]=0; 101 int e=head[u]; 102 while(e) 103 { 104 int v=vet[e]; 105 if(dis[u]+len[e]<dis[v]) 106 { 107 dis[v]=dis[u]+len[e]; 108 if(!inq[v]) 109 { 110 top++; 111 stk[top]=v; 112 inq[v]=1; 113 t[v]++; 114 if(t[v]==n+2) return 0; 115 } 116 } 117 e=nxt[e]; 118 } 119 } 120 return 1; 121 } 122 123 void solve() 124 { 125 n=read(),m1=read(),m2=read(); 126 rep(i,1,m1) a[i].x=read(),a[i].y=read(),a[i].z=read(); 127 rep(i,1,m2) b[i].x=read(),b[i].y=read(),b[i].z=read(); 128 int l=0,r=n,last=n; 129 while(l<=r) 130 { 131 int mid=(l+r)>>1; 132 build(mid); 133 if(isok()){last=mid; r=mid-1;} 134 else l=mid+1; 135 } 136 printf("%d ",last); 137 } 138 139 int main() 140 { 141 //freopen("1.in","r",stdin); 142 int cas=read(); 143 while(cas--) solve(); 144 return 0; 145 }