Intervals poj 3680 最小费用最大流

来源:互联网 发布:匹克模考tpo软件 编辑:程序博客网 时间:2024/05/21 09:57

题目大意

给你n个区间(ai,bi),对应区间的权重为ci。现在让你挑选一些区间,使得任一点出现的次数不超过k,问你满足条件的方案的最大权重和为多少?

分析

离散化后两个端点连边,流量为1,费用为负的权值(因为求的是最大费用最大流),然后再加上源点连一条到1的流量为k,费用为零的边和n到汇点一条到1的流量为k,费用为零的边。
重要的是:i和i+1之间的连边,流量为k,费用为0,因为有的端点之间你要让它们产生联系并且受制与k次。

code

#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<string>#include<algorithm>#include<queue>;using namespace std;struct arr{    int x,y,w,c,next;}edge[200000];int ls[1000];int dis[1000];int f[200000];int v[1000];int sign[1000]; int edge_m;int ans;int s,t;int n,m;int add(int x,int y,int w,int c){    edge_m++;    edge[edge_m]=(arr){x,y,w,c,ls[x]},f[edge_m]=w,ls[x]=edge_m;     edge_m++;    edge[edge_m]=(arr){y,x,w,-c,ls[y]},f[edge_m]=0,ls[y]=edge_m;} bool bfs(){    for (int i=s;i<=t+1;i++) dis[i]=2000000000;    memset(v,0,sizeof(v));    queue<int> q;       dis[s]=0;    v[s]=0;    q.push(s);    do    {        int x=q.front();        q.pop();        for (int i=ls[x];i;i=edge[i].next)        {            if ((dis[edge[i].y]>dis[x]+edge[i].c)&&(f[i]))            {                dis[edge[i].y]=dis[x]+edge[i].c;                sign[edge[i].y]=i;                if (!v[edge[i].y])                {                    v[edge[i].y]=1;                    q.push(edge[i].y);                }            }        }        v[x]=0;    }while (!q.empty());    if (dis[t]!=2000000000)        return true;    else        return false;}void mcf(){    int mn=2000000000;    int x=t;    while (sign[x])    {        mn=min(mn,f[sign[x]]);        x=edge[sign[x]].x;    }    ans+=mn*dis[t];    x=t;    while (sign[x])    {        f[sign[x]]-=mn;        f[sign[x]^1]+=mn;        x=edge[sign[x]].x;    }}int dinic(){    while (bfs())    {        mcf();    }}int main(){    int T;    scanf("%d",&T);    while(T--)      {          scanf("%d%d",&n,&m);        edge_m=1;        memset(edge,0,sizeof(edge));        memset(ls,0,sizeof(ls));        memset(f,0,sizeof(f));        memset(sign,0,sizeof(sign));        s=0; t=0;        for (int i=1;i<=n;i++)        {            int x,y,c;            scanf("%d%d%d",&x,&y,&c);            add(x,y,1,-c);            if (y>t)                t=y;        }        for (int i=1;i<t;i++)            add(i,i+1,200000000,0);        add(s,1,m,0);        add(t,t+1,m,0);        t++;        ans=0;        dinic();        printf("%d\n",-ans);    }    return 0;}
0 0
原创粉丝点击