HDU 6437 Problem L.Videos

版权声明:转载请注明出处,欢迎讨论,共同进步,QQ:1051780721 https://blog.csdn.net/ACM2017/article/details/81989755

http://acm.hdu.edu.cn/showproblem.php?pid=6437
最大费用?先取相反数得最小再取相反数即最大。
最小费用最大流。将每部电影一分为二的拆开,左点连源点s,右点连汇点t,连的都是容量为INF、费用为0的边,左到右点自然连的是容量为1,费用-val的边;
再来一个到源点s的es,它到s连一条容量k(k个人)、费用0;
考虑到电影的时间冲突,O( m 2 m^2 ) for/for,同种电影连的边费用w,否则0

//187MS
#include <bits/stdc++.h>
#define ll long long
#define L(u) u<<1
#define R(u) u<<1|1
using namespace std;
const int MXN = 410;
const int MXM = 100000;
const int INF = 0x3f3f3f3f;
struct data {
    int u,v,cap,flow,cost,nxt;
}g[MXM];
int head[MXN],tot,pre[MXN],dis[MXN];//Here tot start from 0. So head[] should be initialized to -1.
int Que[MXM],l,r;//for SPFA
bool vis[MXN];

void addEdge(int u,int v,int w,int c) {
    g[tot]=(data){u,v,w,0,c,head[u]};
    head[u]=tot++;
    g[tot]=(data){v,u,0,0,-c,head[v]};
    head[v]=tot++;
}

bool SPFA(int s,int t) {
    memset(dis,INF,sizeof dis);
    memset(vis,0,sizeof( vis));
    memset(pre,-1,sizeof pre);
    dis[s]=0;
    vis[s]=true;
    l=-1,r=0,Que[0]=s;
    int u,v;
    data e;
    while (l<r) {
        u = Que[++l];
        vis[u]=false;
        for (int i=head[u];~i;i=g[i].nxt) {
            e=g[i];
            if (dis[e.v]>dis[u]+e.cost&&e.cap>e.flow) {
                dis[e.v]=dis[u]+e.cost;
                pre[e.v]=i;
                if (!vis[e.v]) {
                    vis[e.v]=true;
                    Que[++r]=e.v;
                }
            }
        }
    }
    return pre[t]!=-1;
}

void MCMF(int s,int t,int &cost,int &flow) {
    flow=cost=0;
    int mini;
    while (SPFA(s,t)) {
        mini=INF;
        for (int i=pre[t];~i;i=pre[g[i^1].v]) mini = min(mini,g[i].cap-g[i].flow);
        for (int i=pre[t];~i;i=pre[g[i^1].v]) {
            g[i].flow+=mini;
            g[i^1].flow-=mini;
            cost+=g[i].cost*mini;
        }
        flow += mini;
    }
}

struct movie{
    int s,e,val,op;
}d[201];
int T,n,m,k,u,v,w;
int ansFlow,ansCost,es,s,t;

int main() {
    //freopen("../in","r",stdin);
    scanf("%d",&T);
    while (T--) {
        tot=0;
        memset(head,-1,sizeof head);
        scanf("%d%d%d%d",&n,&m,&k,&w);
        for (int i=1;i<=m;++i) scanf("%d%d%d%d",&d[i].s,&d[i].e,&d[i].val,&d[i].op);
        es=0,s=1,t=m*2+2;
        addEdge(es,s,k,0);//There are k person in all.
        for (int i=1;i<=m;++i) {
            addEdge(s,L(i),m,0);//m:INF
            addEdge(L(i),R(i),1,-d[i].val);
            addEdge(R(i),t,m,0);
        }
        for (int i=1;i<=m;++i)
            for (int j=1;j<=m;++j)
                if (i!=j&&d[i].e<=d[j].s) {
                    if (d[i].op==d[j].op) addEdge(R(i),L(j),m,w);//m:INF
                    else addEdge(R(i),L(j),m,0);
                }
        MCMF(es,t,ansCost,ansFlow);
        printf("%d\n",-ansCost);
    }

    return 0;
}


猜你喜欢

转载自blog.csdn.net/ACM2017/article/details/81989755
今日推荐