poj 3680 Intervals
生活随笔
收集整理的這篇文章主要介紹了
poj 3680 Intervals
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
給定N個帶權的開區間,第i個區間覆蓋區間(ai,bi),權值為wi。現在要求挑出一些區間使得總權值最大,并且滿足實軸上任意一個點被覆蓋不超過K次。
1<=K<=N<=200.1<=ai<bi<=100000.1<=wi<=100000.
最小費用最大流。
將所有區間端點離散化到整數1到M,每個數對應一個點。
源點向整數1點連一條容量為K費用為0的邊。
整數i點向整數i+1點連一條容量為正無窮費用為0的邊。(1<=i<M).
整數M點向匯點連一條容量為正無窮費用為0的邊。
每個區間由aai點向bbi點連一條容量為1費用為-wi的邊(aai和bbi為區間左右端點離散后的值)。
最小費用最大流取反即為答案。
考慮對于一條aai向bbi的邊,費用為負值必然優先選擇,使得區間(aai,bbi)剩余流量減一,對應題中(ai,bi)的點剩余覆蓋次數減一。注意到本題區間為開區間,所以兩個區間相連不影響結果。
1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #include<queue> 6 using namespace std; 7 const int dian=405; 8 const int bian=1505; 9 const int INF=0x3f3f3f3f; 10 int zkh[dian],ykh[dian],khqz[dian]; 11 int zl[dian],yl[dian]; 12 int h[dian],nxt[bian],ver[bian],val[bian],cos[bian],minn[dian],with[dian]; 13 int v[dian],d[dian]; 14 int n,k,tot,bula; 15 int S,T; 16 void add(int a,int b,int c,int d){ 17 tot++;ver[tot]=b;val[tot]=c;cos[tot]=d;nxt[tot]=h[a];h[a]=tot; 18 tot++;ver[tot]=a;val[tot]=0;cos[tot]=-d;nxt[tot]=h[b];h[b]=tot; 19 } 20 bool tell(){ 21 memset(v,0,sizeof(v)); 22 memset(d,0x3f,sizeof(d)); 23 memset(with,0,sizeof(with)); 24 memset(minn,0x3f,sizeof(minn)); 25 queue<int>q; 26 q.push(S); 27 v[S]=1; 28 d[S]=0; 29 while(!q.empty()){ 30 int x=q.front(); 31 q.pop(); 32 v[x]=0; 33 for(int i=h[x];i;i=nxt[i]){ 34 int y=ver[i]; 35 if(d[y]>d[x]+cos[i]&&val[i]){ 36 d[y]=d[x]+cos[i]; 37 minn[y]=min(minn[x],val[i]); 38 with[y]=i; 39 if(!v[y]){ 40 v[y]=1; 41 q.push(y); 42 } 43 } 44 } 45 } 46 if(d[T]==0x3f3f3f3f) 47 return 0; 48 return 1; 49 } 50 int zeng(){ 51 for(int i=T;i!=S;i=ver[with[i]^1]){ 52 val[with[i]]-=minn[T]; 53 val[with[i]^1]+=minn[T]; 54 } 55 return minn[T]*d[T]; 56 } 57 int dinic_cost(){ 58 int r=0; 59 while(tell()) 60 r+=zeng(); 61 return r; 62 } 63 int main(){ 64 int cas; 65 scanf("%d",&cas); 66 while(cas--){ 67 memset(h,0,sizeof(h)); 68 memset(nxt,0,sizeof(nxt)); 69 tot=1; 70 bula=0; 71 scanf("%d%d",&n,&k); 72 for(int i=1;i<=n;i++) 73 scanf("%d%d%d",&zkh[i],&ykh[i],&khqz[i]); 74 //本人太過蒟蒻,下文大段while語句(離散化)不知所云,建議跳過。 75 int hhd; 76 while(1){ 77 hhd=INF; 78 for(int i=1;i<=n;i++) 79 if(hhd>zkh[i]) 80 hhd=zkh[i]; 81 if(hhd==INF) 82 break; 83 bula++; 84 for(int i=1;i<=n;i++) 85 if(hhd==zkh[i]){ 86 if(ykh[i]==INF){ 87 zkh[i]=INF; 88 yl[i]=bula; 89 } 90 else{ 91 zkh[i]=ykh[i]; 92 ykh[i]=INF; 93 zl[i]=bula; 94 } 95 } 96 } 97 S=bula+1,T=bula+2; 98 for(int i=1;i<bula;i++) 99 add(i,i+1,INF,0); 100 add(S,1,k,0); 101 add(bula,T,INF,0); 102 for(int i=1;i<=n;i++) 103 add(zl[i],yl[i],1,-khqz[i]); 104 printf("%d\n",-dinic_cost()); 105 } 106 return 0; 107 }?
轉載于:https://www.cnblogs.com/dugudashen/p/6223955.html
總結
以上是生活随笔為你收集整理的poj 3680 Intervals的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CF722D. Generating S
- 下一篇: UI 07 _ 导航视图控制器 与 属性