题意:n个区间,每个区间都有权值,尽可能的去取区间,但要保证每个点不被取超过k次。
题解:
主要就是建图:我是不会建。。我太笨了。
首先,我们不可能每个点使其都存在。太多了。所以我们就取每个区间的端点。这样,每个端点之间的流量为k,费用为权值。但是,为了确保我们不想取这个区间时有别的选择,就把所有的点从小到大 连起来,流量为k,为用为0。这样当我们不想取某个区间时,就从费用为零的边上流过就行了。
另:要把端点离散化,排序,重编号。
#include<stdio.h>
#include<algorithm>
#include<string.h>
#define MX 10000000
#define nMax 500
#define eMax 10000
using namespace std;
struct Egde{
int u,v,c,w,next,pre;
}eg[eMax];
int n, m, ans,vs,vt,cas,K;
int k, list[nMax];
int que[nMax], pre[nMax], dis[nMax];
struct interval{
int x,y,w;
}inl[210];
int hash[100010];
bool vis[nMax];
void add(int u, int v, int c, int w){
eg[k].u=u;eg[k].v=v;eg[k].pre=k+1;eg[k].next=list[u];eg[k].c=c;eg[k].w=w;list[u]=k++;
eg[k].u=v;eg[k].v=u;eg[k].pre=k-1;eg[k].next=list[v];eg[k].c=0;eg[k].w=-w;list[v]=k++;
}
bool spfa(){
int i, head = 0, tail = 1;
for(i = vs; i <= vt; i ++){
dis[i] = MX;
vis[i] = false;
}
dis[vs] = 0;
que[0] = vs;
vis[vs] = true;
while(tail != head){
int u = que[head ++];
for(i = list[u]; i != -1; i = eg[i].next){
int v = eg[i].v;
if(eg[i].c&& dis[v] > dis[u] + eg[i].w){
dis[v] = dis[u] + eg[i].w;
pre[v] = i;
if(!vis[v]){
vis[v] = true;
que[tail ++] = v;
}
}
}
vis[u] = false;
}
if(dis[vt] == MX) return false;
return true;
}
void end(){
int u, p, sum = MX;
for(u = vt; u != vs; u = eg[eg[p].pre].v){
p = pre[u];
eg[p].c -=1;
eg[eg[p].pre].c += 1;
ans +=-1*eg[p].w;
}
}
int main(){
scanf("%d",&cas);
while(cas--){
k=0;
ans = 0;
memset(list,-1,sizeof(list));
memset(hash,0,sizeof(hash));
scanf("%d%d",&n,&K);
int kk=1;
for(int i=0;i<n;i++){
scanf("%d%d%d",&inl[i].x,&inl[i].y,&inl[i].w);
hash[inl[i].x]=hash[inl[i].y]=1;
}
for(int i=0;i<=100000;i++){
if(hash[i]==1){
hash[i]=kk++;
}
}
for(int i=0;i<n;i++){
inl[i].x=hash[inl[i].x];
inl[i].y=hash[inl[i].y];
}
vs=0;vt=kk;
for(int i=vs;i<vt;i++){
add(i,i+1,K,0);
}
for(int i=0;i<n;i++){
add(inl[i].x,inl[i].y,1,-inl[i].w);
}
while(spfa()) {
end();
}
printf("%d\n",ans);
}
return 0;
}