poj 3680(最小费用流)

来源:互联网 发布:在墨尔本生活知乎 编辑:程序博客网 时间:2024/06/05 15:11

传送门
问题:数轴上有若干个带权值的闭区间(刘汝佳蓝书P367写的是左闭右开区间,个人根据样例数据和解法推测应该是笔误),选出一些区间使权值和尽量大且任意一个数均被覆盖k次

题解:经典的最小费用流模型,连边方法写在代码开头,具体为什么要这样连边本蒟蒻也不易表述清楚,但是在纸上模拟几组数据发现确实是对的,应该还是很好理解的,实在理解不了的—>戳这儿

注意:区间最好先离散化,最后答案是费用的相反数

/*    for every interval, adde(u,v,1,w);    for i=1~(tot-1), adde(i,i+1,INF,0);    adde(0,1,k,0), adde(tot,tot+1,k,0)*/#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<map>#include<queue>using namespace std;const int maxn=101000;const int INF=0x3f3f3f3f;int n,k;int head[maxn],edge,source,sink;struct EDGE {    int u,v,nxt,r,c;}e[maxn];int dis[maxn],pre[maxn];bool inq[maxn];int a[maxn],b[maxn],c[maxn],f[maxn<<1],tot;int mp[maxn];inline void adde(int u,int v,int r,int c) {    e[edge].u=u,e[edge].v=v,e[edge].nxt=head[u],e[edge].r=r,e[edge].c=c,head[u]=edge++;    e[edge].u=v,e[edge].v=u,e[edge].nxt=head[v],e[edge].r=0,e[edge].c=-c,head[v]=edge++;}inline bool spfa() {    queue<int> q;    memset(inq,false,sizeof(inq));    memset(dis,INF,sizeof(dis));    dis[source]=0,q.push(source),inq[source]=true,pre[source]=-1;    while (!q.empty()) {        int p=q.front();        q.pop(),inq[p]=false;        for (int i=head[p];~i;i=e[i].nxt) {            int v=e[i].v;            if (e[i].r>0&&dis[v]>dis[p]+e[i].c) {                pre[v]=i,                dis[v]=dis[p]+e[i].c;                if (!inq[v]) {                    inq[v]=true;                    q.push(v);                }            }        }    }    return dis[sink]^INF;}inline int MCMF() {    int ans=0;    while (spfa()) {        int tmp=INF;        for (int i=pre[sink];~i;i=pre[e[i].u]) tmp=min(tmp,e[i].r);        ans+=tmp*dis[sink];        for (int i=pre[sink];~i;i=pre[e[i].u]) e[i].r-=tmp,e[i^1].r+=tmp;    }    return -ans;}inline int read() {    int x=0,f=1;char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();    return x*f;}int main() {//  freopen("poj 3680.in","r",stdin);    int kase=read();    while (kase--) {        memset(head,-1,sizeof(head));        edge=0;        f[0]=0,tot=0;        n=read(),k=read();        for (int i=1;i<=n;++i) {            a[i]=read(),b[i]=read(),c[i]=read();            f[(i<<1)-1]=a[i],f[i<<1]=b[i];        }        sort(f+1,f+(n<<1)+1);        int nn=n<<1;        for (int i=1;i<=nn;++i)            if (f[i]!=f[i-1]) mp[f[i]]=++tot;//discretize intervals        for (int i=1;i<tot;++i)            adde(i,i+1,INF,0);        source=0,sink=tot+1;        adde(source,1,k,0),adde(tot,sink,k,0);        for (int i=1;i<=n;++i)            adde(mp[a[i]],mp[b[i]],1,-c[i]);        printf("%d\n",MCMF());    }    return 0;}
原创粉丝点击