bzoj5037: [Jsoi2014]电信网络

bzoj5037: [Jsoi2014]电信网络


http://www.lydsy.com/JudgeOnline/problem.php?id=5037

考虑约束关系的实质即是选择一个点必须选择能被他到达的点,考虑最小割建图。

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 505;

struct node {
    int to, next, flow, neg;
} edge[MAXN*MAXN*3];
int head[MAXN], top = 0;
const int S = MAXN-1, T = MAXN-2;
inline void push(int i, int j, int f)
{
    ++top, edge[top] = (node){j, head[i], f, top+1}, head[i] = top;
    ++top, edge[top] = (node){i, head[j], 0, top-1}, head[j] = top;
}

int vis[MAXN], bfstime, lev[MAXN];
int cur[MAXN];
int q[MAXN], L, R;
bool bfs()
{
    L = 1, R = 0, q[++R] = S, vis[S] = ++bfstime, lev[S] = 0;
    while (L <= R) {
        int nd = q[L++];
        for (int i = head[nd]; i; i = edge[i].next) {
            int to = edge[i].to;
            if (vis[to] == bfstime || edge[i].flow == 0) continue;
            lev[to] = lev[nd]+1, vis[to] = bfstime, q[++R] = to;
        }
    }
    return vis[T] == bfstime;
}

int dfs(int nd, int flow)
{
    if (nd == T || flow == 0) return flow;
    int ans = 0, t;
    for (int &i = cur[nd]; i; i = edge[i].next) {
        int to = edge[i].to;
        if (lev[to] != lev[nd]+1 || edge[i].flow == 0) continue;
        t = dfs(to, min(flow, edge[i].flow));
        ans += t, flow -= t, edge[i].flow -= t, edge[edge[i].neg].flow += t;
    }
    return ans;
}

int dinic()
{
    int ans = 0;
    while (bfs()) memcpy(cur, head, sizeof head), ans += dfs(S, INT_MAX);
    return ans;
}

int n;
int x[MAXN], y[MAXN], r[MAXN], s[MAXN];

int main()
{
    scanf("%d", &n);
    int INF = 1e5;
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d%d", &x[i], &y[i], &r[i], &s[i]);
        push(S, i, INF), push(i, T, -s[i]+INF);
    }
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            if (i == j) continue;
            if ((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]) > r[i]*r[i]) continue;
            push(i, j, INT_MAX);
        }
    cout << -(dinic()-n*INF) << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值