【差分約束】POJ1201/LG SP116 Intervals
阿新 • • 發佈:2018-12-22
題意翻譯 區間取數 題目描述 有n個區間,在區間[ai,bi]中至少取任意互不相同的ci個整數。求在滿足n個區間的情況下,至少要取多少個正整數。 輸入輸出格式 輸入格式 多組資料。 第一行的一個整數T表示資料個數。對於每組資料,第一行包含一個整數nn(11<=nn<=5000050000)表示區間數。以下nn行描述區間。輸入的第(i+1)行包含三個整數ai,bi,ci,由空格分開。其中0<=ai<=bi<=50000,1<=ci<=bi-ai+1。 輸出格式 對於每組資料,輸出一個對於n個區間[ai,bi] 至少取ci個不同整數的數的總個數。 輸入輸出樣例 輸入樣例#T1: 1 5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1 輸出樣例#1: 6
這道題呢又是一個差分約束
很明顯通過題意可以抽象出很多個b-(a-1)>=c
而且還有一點隱藏的東西1>=i-(i-1)>=0
轉換一下下就是i-(i-1)>=0,i-(i-1)>=-1
因為是大於,所以差分的時候要跑最長路
再次記憶一下,b-a>=a,建a到b的單向邊
然後堆疊spfa就能A了
程式碼
1 #include<cstdio> 2 #include<queue> 3#include<cstring> 4 #define N 50011 5 using namespace std; 6 struct star{int to,nxt,val;}edge[10*N]; 7 int dis[N],head[N],stk[N],mi=0x7f7f7f7f,ma=-1; 8 int cnt=1,n,a,b,c,top,t; 9 bool in[N]; 10 inline void add(int u,int v,int w) 11 { 12 edge[cnt].nxt=head[u]; 13 edge[cnt].to=v;14 edge[cnt].val=w; 15 head[u]=cnt++; 16 } 17 int main() 18 { 19 scanf("%d",&t); 20 while(t--) 21 { 22 memset(head,-1,sizeof(head)); 23 memset(dis,~0x7f,sizeof(dis)); 24 cnt=1; 25 scanf("%d",&n); 26 for(int i=1;i<=n;i++) 27 { 28 scanf("%d%d%d",&a,&b,&c); 29 add(a-1,b,c); 30 mi=min(a-1,mi); 31 ma=max(ma,b); 32 } 33 for(int i=mi;i<=ma;i++) 34 add(i,i-1,-1),add(i-1,i,0); 35 stk[++top]=mi; 36 dis[mi]=0,in[mi]=1; 37 while(top) 38 { 39 int now=stk[top--];in[now]=0; 40 for(int i=head[now];i!=-1;i=edge[i].nxt) 41 { 42 int to=edge[i].to; 43 if(dis[to]<dis[now]+edge[i].val) 44 { 45 dis[to]=dis[now]+edge[i].val; 46 if(!in[to]) 47 {stk[++top]=to;in[to]=1;} 48 } 49 } 50 } 51 printf("%d\n",dis[ma]); 52 } 53 return 0; 54 }