这是一个最大权闭合子图问题。
之所以会有最大权闭合子图问题的主要原因是因为这个图中存在一部分点的权值是负数。
对最大权闭合子图的解释在这个链接最大权闭合子图
对这道题的解释在这个链接题目思路
经过测试,分数为100
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<cmath>
#include<queue>
typedef long long LL;
#define MAX1 20050
#define DEBUG
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
struct edge {
int to;
LL cap;
int rev;
}Edges[MAX1];
struct Des {
LL L, R, a, b, c;
}des[MAX1];
vector<edge>G[MAX1];
int level[MAX1];
int iter[MAX1];
void add_edge(int from,int to,LL cap)
{
G[from].push_back({ to,cap,(int)G[to].size() });
G[to].push_back({ from,0,(int)G[from].size() - 1 });
}
void BFS(int s)
{
memset(level, -1, sizeof(level));
queue<int>que;
level[s] = 0;
que.push(s);
while (!que.empty())
{
int v = que.front();
que.pop();
for (int i = 0; i < G[v].size(); i++)
{
edge& e = G[v][i];
if (e.cap > 0 && level[e.to] < 0)
{
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
}
int DFS(int v, int t, LL f)
{
if (v == t)return f;
for (int &i = iter[v]; i < G[v].size(); i++)
{//iter实际上是替代了used数组的作用
edge& e = G[v][i];
if (e.cap > 0&&level[v]<level[e.to])
{
int d = DFS(e.to, t, min(f, e.cap));
if (d > 0)
{
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
LL twofun(int x,int i)
{
return des[i].a * x * x + des[i].b * x + des[i].c;
}
//在边界上取值
LL Boundary(int i)
{
LL Left = twofun(des[i].L, i);
LL Right = twofun(des[i].R, i);
return max(Left, Right);
}
LL calcu(int i)
{
int l = des[i].L + 1;
int r = des[i].R - 1;
//中间轴
if (l > r)
return 0;
if (des[i].a > 0)
{
return max(twofun(l, i), twofun(r, i));
}
if (des[i].a < 0)
{
double center = -des[i].b / 2.0 / des[i].a;
if (center >r)
return twofun(r, i);
else if (center <l)
{
return twofun(l, i);
}
else {
return max( twofun(floor(center), i),twofun(ceil(center),i));
}
}
if (des[i].b > 0)
return twofun(r, i);
else
{
return twofun(l, i);
}
}
LL max_flow(int s, int t)
{
LL flow = 0;
while (true)
{
BFS(s);
if (level[t] < 0)return flow;
memset(iter, 0, sizeof(iter));
int f;
while ((f=DFS(s,t,INF))>0)
{
flow += f;
}
}
return 0;
}
int main()
{
#ifdef DEBUG
freopen("sb.txt", "r", stdin);
#endif // DEBUG
int countA, countB;
cin >> countA >> countB;
LL possum = 0;
int MAX = 2 * countA + 1;//汇点以后最好就按照这个方法来计算
for (int i = 1; i <= countA; i++)
{
scanf("%lld %lld %lld %lld %lld", &des[i].L, &des[i].R, &des[i].a, &des[i].b, &des[i].c);
LL v1 = calcu(i);//第一类点
LL v2 = Boundary(i)-v1;
possum += max((LL)0, v1) + max((LL)0, v2);
add_edge(i+countA,i,INF);
if (v1 > 0)
{
add_edge(0,i,v1);
}
else if(v1<0)
{
add_edge(i, MAX, -v1);
}
if (v2 > 0)
{
add_edge(0,i+countA,v2);
}
else if(v2<0)
{
add_edge(i+countA,MAX,-v2);
}
}
//int possum = 0;
for (int i = 0; i < countB; i++)
{
int pointA, pointB, z;
scanf("%d %d %d", &z ,&pointA, &pointB);
if (z == 1)
{
add_edge(pointB, pointA, INF);
}
else
{
add_edge(pointB + countA, pointA, INF);
}
}
cout <<possum- max_flow(0, MAX);
return 0;
}