IntervalsTime Limit:5000MSMemory Limit:65536KTotal Submissions:7161Accepted:2982
Description
You are givenNweighted open intervals. Theith interval covers (ai,bi) and weighswi. Your task is to pick some of the intervals to maximize the total weights under the limit that no point in the real axis is covered more thanktimes.
Input
The first line of input is the number of test case.
The first line of each test case contains two integers,NandK(1 ≤K≤N≤ 200).
The nextNline each contain three integersai,bi,wi(1 ≤ai<bi≤ 100,000, 1 ≤wi≤ 100,000) describing the intervals.
There is a blank line before each test case.
Output
For each test case output the maximum total weights in a separate line.
Sample Input
43 11 2 22 3 43 4 83 11 3 22 3 43 4 83 11 100000 1000001 2 3100 200 3003 21 100000 1000001 150 301100 200 300
Sample Output
1412100000100301
Source
POJ Founder Monthly Contest – 2008.07.27, windy7926778費(fèi)用流,構(gòu)圖方法很巧妙,
poj3680 Intervals
。我一開始的想法是區(qū)間放左邊,點(diǎn)放右邊,跑費(fèi)用流。后來發(fā)現(xiàn)顯然是錯(cuò)的,因?yàn)樵谧畲罅鲿r(shí)源點(diǎn)流入?yún)^(qū)間的邊不一定滿流,也就是一個(gè)區(qū)間內(nèi)的點(diǎn)沒有全部覆蓋,這顯然是錯(cuò)誤的。
下面是正確地做法:要保證每個(gè)點(diǎn)最多覆蓋k次,可以把所有點(diǎn)串聯(lián)起來,每個(gè)點(diǎn)向后一個(gè)點(diǎn)連一條容量k、費(fèi)用0的邊。(是不是很機(jī)智。!)然后對于區(qū)間[a,b],從a到b連一條容量1、費(fèi)用w的邊就可以了。最后從源點(diǎn)到1點(diǎn)、從n點(diǎn)到匯點(diǎn),分別連一條容量k、費(fèi)用0的點(diǎn)。
至于這個(gè)方法的正確性如何證明呢??我可以說只可意會不可言傳嗎=_=……大家自己腦補(bǔ)吧……額
如此看來,構(gòu)圖真是一種藝術(shù)啊!
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include#include<queue>#include<map>#define F(i,j,n) for(int i=j;i<=n;i++)#define D(i,j,n) for(int i=j;i>=n;i--)#define LL long long#define pa pair<int,int>#define maxn 1000#define maxm 1000#define inf 1000000000using namespace std;int tt,n,k,s,t,cnt,ans,tot;int head[maxn],dis[maxn],p[maxn],a[maxn],b[maxn],w[maxn],f[maxn];bool inq[maxn];map<int,int>mp;struct edge_type{ int from,to,next,v,c;}e[maxm];inline int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}inline void add_edge(int x,int y,int v,int c){ e[++cnt]=(edge_type){x,y,head[x],v,c};head[x]=cnt; e[++cnt]=(edge_type){y,x,head[y],0,-c};head[y]=cnt;}inline bool spfa(){ queue<int>q; memset(inq,false,sizeof(inq)); F(i,1,t) dis[i]=inf; dis[s]=0;q.push(s);inq[s]=true; while (!q.empty()) { int x=q.front();q.pop();inq[x]=false; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (e[i].v&&dis[y]>dis[x]+e[i].c) { dis[y]=dis[x]+e[i].c; p[y]=i; if (!inq[y]){q.push(y);inq[y]=true;} } } } return dis[t]!=inf;}inline void mcf(){ ans=0; while (spfa()) { int tmp=inf; for(int i=p[t];i;i=p[e[i].from]) tmp=min(tmp,e[i].v); ans+=tmp*dis[t]; for(int i=p[t];i;i=p[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;} }}int main(){ tt=read(); while (tt--) { memset(head,0,sizeof(head)); memset(p,0,sizeof(p)); memset(f,0,sizeof(f)); cnt=1;tot=0; n=read();k=read(); F(i,1,n) { a[i]=read();b[i]=read();w[i]=read(); f[2*i-1]=a[i];f[2*i]=b[i]; } sort(f+1,f+2*n+1); F(i,1,2*n) if (i==1||f[i]!=f[i-1]) mp[f[i]]=++tot; s=tot+1;t=tot+2; F(i,1,tot-1) add_edge(i,i+1,k,0); add_edge(s,1,k,0);add_edge(tot,t,k,0); F(i,1,n) add_edge(mp[a[i]],mp[b[i]],1,-w[i]); mcf(); printf("%d\n",-ans); }}</int></int,int></int,int></map></queue></cmath></cstring></cstdlib></cstdio></iostream>