CCF CSP 2020-06-05 乔乔和牛牛逛超市

买了x才能买y 等价于要想得到y的最大收益就必须连带着把x的最大收益(即使可能<0)也得收下,这个模型是典型的最大权闭合子图,答案应该是图中正的点权和-最小割的容量。最小割跑最大流模板就可得到。但是第二类点的建图方式还没想到,可能是需要拆点。

80分代码(边建反了) 就这也能拿80分? ccf数据好水啊

#include 
#include 
#include 
#include 
#define LL long long
using namespace std;
const int N = 100010, M = 2000010;
const LL INF = 2e9;
int n,m,S,T;
int h[N],tot;
struct Edge{
    int to,nxt;
    LL f;
}e[M];
int q[N],d[N],cur[N],w[N];
void add(int a,int b,LL c)
{
    e[tot].to = b, e[tot].f = c, e[tot].nxt = h[a], h[a] = tot ++;
    e[tot].to = a, e[tot].f = 0, e[tot].nxt = h[b], h[b] = tot ++;
}
bool bfs()
{
    memset(d, -1, sizeof d);
    int hh = 0, tt = -1;
    q[++ tt] = S; d[S] = 0; cur[S] = h[S];
    while(hh <= tt)
    {
        int u = q[hh ++];
        for(int i = h[u]; ~i; i = e[i].nxt)
        {
            int to = e[i].to;
            if(d[to] == -1 && e[i].f)
            {
                d[to] = d[u] + 1;
                cur[to] = h[to];
                q[++ tt] = to;
                if(to == T) return true;
            }
        }
    }
    return false;
}
LL dfs(int u,int limit)
{
    if(u == T) return limit;
    LL flow = 0;
    for(int i = cur[u]; ~i && flow < limit; i = e[i].nxt)
    {
        cur[u] = i;
        int to = e[i].to;
        if(d[to] == d[u] + 1 && e[i].f)
        {
            LL f = dfs(to, min(e[i].f, limit - flow));
            if(!f) d[to] = -1;
            e[i].f -= f, e[i ^ 1].f += f, flow += f;
        }
    }
    return flow;
}
LL dinic()
{
    LL r = 0, flow;
    while(bfs()) while(flow = dfs(S,INF)) r += flow;
    return r;
}
int gety(int a, int b, int c,int x)
{
    return a * x * x + b * x + c;
}
int cal(int a,int b, int c, int l, int r)
{
    int w = -INF;
    if(a > 0) w = max(gety(a, b, c, l), gety(a, b, c, r));
    
    else if(a < 0)
    {
        int p = round(-(double)b / (2 * a));
        if(p < l) w = gety(a, b, c, l);
        else if(p > r) w = gety(a, b, c, r);
        else w = gety(a, b, c, p);
    }
    else
    {
        if(b > 0) w = gety(a, b, c, r);
        else w = gety(a, b, c, l);
    }
    return w;
}
int main()
{
    memset(h, -1, sizeof h);
    cin >> n >> m;
    S = 0, T = n * 2 + 1;
    for(int i = 1; i <= n; ++i)
    {
        int l, r, a, b, c;
        scanf("%d%d%d%d%d",&l, &r, &a, &b, &c);
        w[i] = cal(a, b, c, l + 1, r - 1);
        w[i + n] = max(gety(a, b, c, l),gety(a, b, c, r)) - w[i];
        add(i + n, i, INF);
    }
        
    for(int i = 0; i < m; ++i)
    {
        int x, y, z; scanf("%d%d%d",&z, &x, &y);
        if(z == 1) add(x, y, INF);
        else add(x + n, y, INF); // 2e5
    }
    LL sum = 0;
    for(int i = 1; i <= n * 2; ++i)
    {
        //cout << w[i] << ' '  << i << '\n';
        if(w[i] < 0) add(i, T, -w[i]);
        else if(w[i] > 0) add(S, i, w[i]), sum += w[i];
    }
    cout << sum - dinic();
}

100分代码:(swap一下输入的边)

#include 
#include 
#include 
#include 
#define LL long long
using namespace std;
const int N = 100010, M = 2000010;
const LL INF = 2e9;
int n,m,S,T;
int h[N],tot;
struct Edge{
    int to,nxt;
    LL f;
}e[M];
int q[N],d[N],cur[N],w[N];
void add(int a,int b,LL c)
{
    e[tot].to = b, e[tot].f = c, e[tot].nxt = h[a], h[a] = tot ++;
    e[tot].to = a, e[tot].f = 0, e[tot].nxt = h[b], h[b] = tot ++;
}
bool bfs()
{
    memset(d, -1, sizeof d);
    int hh = 0, tt = -1;
    q[++ tt] = S; d[S] = 0; cur[S] = h[S];
    while(hh <= tt)
    {
        int u = q[hh ++];
        for(int i = h[u]; ~i; i = e[i].nxt)
        {
            int to = e[i].to;
            if(d[to] == -1 && e[i].f)
            {
                d[to] = d[u] + 1;
                cur[to] = h[to];
                q[++ tt] = to;
                if(to == T) return true;
            }
        }
    }
    return false;
}
LL dfs(int u,int limit)
{
    if(u == T) return limit;
    LL flow = 0;
    for(int i = cur[u]; ~i && flow < limit; i = e[i].nxt)
    {
        cur[u] = i;
        int to = e[i].to;
        if(d[to] == d[u] + 1 && e[i].f)
        {
            LL f = dfs(to, min(e[i].f, limit - flow));
            if(!f) d[to] = -1;
            e[i].f -= f, e[i ^ 1].f += f, flow += f;
        }
    }
    return flow;
}
LL dinic()
{
    LL r = 0, flow;
    while(bfs()) while(flow = dfs(S,INF)) r += flow;
    return r;
}
int gety(int a, int b, int c,int x)
{
    return a * x * x + b * x + c;
}
int cal(int a,int b, int c, int l, int r)
{
    int w = -INF;
    if(a > 0) w = max(gety(a, b, c, l), gety(a, b, c, r));
    
    else if(a < 0)
    {
        int p = round(-(double)b / (2 * a));
        if(p < l) w = gety(a, b, c, l);
        else if(p > r) w = gety(a, b, c, r);
        else w = gety(a, b, c, p);
    }
    else
    {
        if(b > 0) w = gety(a, b, c, r);
        else w = gety(a, b, c, l);
    }
    return w;
}
int main()
{
    memset(h, -1, sizeof h);
    cin >> n >> m;
    S = 0, T = n * 2 + 1;
    for(int i = 1; i <= n; ++i)
    {
        int l, r, a, b, c;
        scanf("%d%d%d%d%d",&l, &r, &a, &b, &c);
        w[i] = cal(a, b, c, l + 1, r - 1);
        w[i + n] = max(gety(a, b, c, l),gety(a, b, c, r)) - w[i];
        add(i + n, i, INF);
    }
        
    for(int i = 0; i < m; ++i)
    {
        int x, y, z; scanf("%d%d%d",&z, &x, &y);
        swap(x, y);
        if(z == 1) add(x, y, INF);
        else add(x + n, y, INF); // 2e5
    }
    LL sum = 0;
    for(int i = 1; i <= n * 2; ++i)
    {
        //cout << w[i] << ' '  << i << '\n';
        if(w[i] < 0) add(i, T, -w[i]);
        else if(w[i] > 0) add(S, i, w[i]), sum += w[i];
    }
    cout << sum - dinic();
}

 

你可能感兴趣的:(网络流,CCF)