UVA12125 题解
题意简述
有
输出哪些点可以让所有的猪运到这个点,若没有输出
思路
考虑使用网络最大流求解。
每个点最开始有
每个点最多能被经过
其余连边直接使用距离公式,若距离小于等于
然后枚举每个点当汇点,若最大流量等于猪的总数,则当前点可以让所有猪运到这个点。
记得多测要清空。
Code
#define x first
#define y second
using namespace std;
const int N = 205, M = (600 + 200 * 199) * 2, inf = 1e8;
const double eps = 1e-8;
struct Edge{
int e, to, nxt;
}g[M];
int h[N], idx = 1;
int dep[N], now[N], q[N];
pair<int, int> p[N];
int S, T;
void add(int a,int b,int c)
{
g[++idx] = {c, b, h[a]}, h[a] = idx;
g[++idx] = {0, a, h[b]}, h[b] = idx;
}
inline double dist(int i,int j)
{
return sqrt((p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y));
}
bool bfs()
{
memset(dep, 0, sizeof dep);
dep[S] = 1;
int hh = 0, tt = 0;
q[0] = S;
now[S] = h[S];
while (hh <= tt)
{
int t = q[hh ++];
for (int i = h[t]; i; i = g[i].nxt)
{
int j = g[i].to;
if (dep[j] || !g[i].e)
continue;
dep[j] = dep[t] + 1;
now[j] = h[j];
if (j == T)
return true;
q[++ tt] = j;
}
}
return false;
}
int find(int u,int lim)
{
if (u == T)
return lim;
int flow = 0;
for (int i = now[u]; i && flow < lim; i = g[i].nxt)
{
now[u] = i;
int j = g[i].to;
if (dep[j] != dep[u] + 1 || !g[i].e)
continue;
int v = find(j, min(g[i].e, lim - flow));
if (!v)
dep[j] = 0;
else
{
g[i].e -= v;
g[i ^ 1].e += v;
flow += v;
}
}
return flow;
}
int dinic()
{
int res = 0, flow;
while (bfs())
while (flow = find(S, inf))
res += flow;
return res;
}
void work()
{
memset(h, 0, sizeof h);
idx = 1;
int n, sum = 0;
double D;
scanf("%d%lf", &n, &D);
for (int i=1;i<=n;i++)
{
int x, y, a, b;
scanf("%d%d%d%d", &x, &y, &a, &b);
p[i] = {x, y};
add(S, i, a);
add(i, i + n, b);
sum += a;
}
for (int i=1;i<n;i++)
for (int j=i+1;j<=n;j++)
if (D - dist(i, j) > eps)
{
add(i + n, j, inf);
add(j + n, i, inf);
}
bool no = true;
for (int i=1;i<=n;i++)
{
for (int j=2;j<=idx;j+=2)
{
g[j].e += g[j ^ 1].e;
g[j ^ 1].e = 0;
}
T = i;
if (dinic() == sum)
{
no = false;
printf("%d ", i - 1);
}
}
if (no)
puts("-1");
else
putchar('\n');
}
不建议直接复制代码提交。