题目大意:
给定n,m,K,W
表示n个小时 m场电影(分为类型A、B)
K个人 若某个人连续看了两场相同类型的电影则失去W 电影时间不能重叠
接下来给定m场电影的 s t w op
表示电影的 开始时间s 结束时间t 看完这场电影则获得w 电影类型是op(0为A 1为B)
将一场电影拆成两个点 s t,两点间连线花费为-w容量为1
源点与所有电影的s点连线 花费为0容量为1
所有电影的t点与汇点连线 花费为0容量为1
若两场电影的时间不冲突 那么按时间顺序在之间连边
若类型相同 花费为W容量为1 否则 花费为0容量为1
最后设超级源点与源点连边 花费为0容量为K 表示最多K个人
此时求出的 最小花费最大流 的最小花费 就是 最后最少的失去
最少的失去 就是 最大的获得的相反数
#include <bits/stdc++.h> using namespace std; #define LL long long #define INF 0x3f3f3f3f #define mem(i,j) memset(i,j,sizeof(i)) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int N=405; const int mod=1e9+7; int n,m; struct NODE { int s,t,w,op; }node[205]; struct Edge { int from,to,cap,flow,cost; Edge(int u,int v,int ca,int f,int co):from(u),to(v),cap(ca),flow(f),cost(co){}; }; struct MCMF { int n,m,s,t; vector<Edge> edges; vector<int> G[N]; int inq[N];//是否在队列中 int d[N];//距离 int p[N];//上一条弧 int v[N];//可改进量 void init(int n) //初始化 顶点为 0~n-1 { this->n=n; for(int i=0;i<=n;i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap,int cost)//加边 { edges.push_back(Edge(from,to,cap,0,cost)); edges.push_back(Edge(to,from,0,0,-cost)); int m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool SPFA(int s,int t,int &flow,int &cost)//寻找最小费用的增广路,使用引用同时修改原flow,cost { for(int i=0;i<n;i++) d[i]=INF; memset(inq,0,sizeof(inq)); d[s]=0;inq[s]=1;p[s]=0;v[s]=INF; queue<int>Q; Q.push(s); while(!Q.empty()) { int u=Q.front(); Q.pop(); inq[u]--; for(int i=0;i<G[u].size();i++) { Edge& e=edges[G[u][i]]; if(e.cap>e.flow && d[e.to]>d[u]+e.cost) {//满足可增广且可变短 d[e.to]=d[u]+e.cost; p[e.to]=G[u][i]; v[e.to]=min(v[u],e.cap-e.flow); if(!inq[e.to]) inq[e.to]++,Q.push(e.to); } } } if(d[t]==INF) return false;//汇点不可达则退出 flow+=v[t]; cost+=d[t]*v[t]; int u=t; while(u!=s) {//更新正向边和反向边 edges[p[u]].flow+=v[t]; edges[p[u]^1].flow-=v[t]; u=edges[p[u]].from; } return true; } int MincotMaxflow(int s,int t) { int flow=0,cost=0; while(SPFA(s,t,flow,cost)); return cost; } }MM; int main() { int _; scanf("%d",&_); while(_--) { int n,m,K,W; scanf("%d%d%d%d",&n,&m,&K,&W); MM.init(2*m+3); inc(i,1,m) { int s,t,w,op; scanf("%d%d%d%d",&s,&t,&w,&op); node[i]={s,t,w,op}; MM.AddEdge(i*2,i*2+1,1,-w); MM.AddEdge(1,i*2,1,0); MM.AddEdge(i*2+1,m*2+2,1,0); } inc(i,1,m) inc(j,i+1,m) { if(node[i].t<=node[j].s) { if(node[i].op==node[j].op) MM.AddEdge(i*2+1,j*2,1,W); else MM.AddEdge(i*2+1,j*2,1,0); } if(node[j].t<=node[i].s) { if(node[i].op==node[j].op) MM.AddEdge(j*2+1,i*2,1,W); else MM.AddEdge(j*2+1,i*2,1,0); } } MM.AddEdge(0,1,K,0); int ans=MM.MincotMaxflow(0,m*2+2); printf("%d\n",-ans); } return 0; }
原文地址:https://www.cnblogs.com/zquzjx/p/10447816.html
时间: 2024-10-01 07:01:40