BZOJ 3955 Surely You Congest 解题报告
首先,我们可以求出源为 $1$ 号点的最短路图以及各个点到 $1$ 号点的最短路。
然后我们考虑那些距离不同的点,是一定不会发生拥堵现象的。
然后我们就只需要考虑那些距离相同的点,就相当于做一个最大流嘛。
假设考虑与 $1$ 号节点距离为 $d$ 的点,那怎么连边,怎么设置源和汇呢?
- 源为 $1$ 号节点,新开一个 $n+1$ 号节点作为汇。
- 对于所有满足 $dist(1, x) + w(x,y) = dist(1, y)$ 的 $x,y$ 建一条 $x\rightarrow y$ 的边,容量为 $1$。
- 如果某个点 $x$ 与 $1$ 号节点距离恰好为 $d$,建一条 $x\rightarrow T$ 的边,容量为这个点上车辆的数目。
然后把所有距离下的最大流加起来,就是答案了。
复杂度看起来有点高,不过加点优化应该还是能跑过去的。
我加了一个优化:如果与 $1$ 号节点距离为 $d$ 的车辆只有 $1$ 辆,那么最大流就是 $1$,就不用去跑网络流了。
感觉效果还不错。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
#define C 2000 + 5
#define N 50000 + 5
#define M 400000 + 5
#define SIZE 10000000 + 5
#define INF 0x7fffffff int n, m, c, S, T, tot, _tot, ans;
int A[C];
int Head[N], _Head[N], Inq[N];
int Dis[N], _Dis[N];
int E[M][];
int q[SIZE]; struct Edge
{
int next, node, flow, w;
}h[M], _h[M]; inline void addedge(int u, int v, int fl, int w)
{
h[++ tot].next = Head[u], Head[u] = tot;
h[tot].node = v, h[tot].flow = fl, h[tot].w = w;
h[++ tot].next = Head[v], Head[v] = tot;
h[tot].node = u, h[tot].flow = , h[tot].w = w;
} inline bool SPFA(int S)
{
for (int i = S; i <= T; i ++)
Dis[i] = INF, Inq[i] = ;
int l = , r = ;
Dis[S] = , q[] = S, Inq[S] = ;
while (l <= r)
{
int z = q[l ++];
Inq[z] = ;
for (int i = Head[z]; i; i = h[i].next)
{
int d = h[i].node, p = h[i].flow, w = h[i].w;
if (!p) continue ;
if (Dis[d] > Dis[z] + w)
{
Dis[d] = Dis[z] + w;
if (!Inq[d])
{
q[++ r] = d;
Inq[d] = r;
}
}
if (Inq[d] && Dis[d] < Dis[q[l]])
{
int u = Inq[d], v = q[l];
q[l] = d, q[u] = v;
Inq[d] = l, Inq[v] = u;
}
}
}
return Dis[T] != INF;
} inline void Copy()
{
_tot = tot;
for (int i = S; i <= T; i ++)
_Head[i] = Head[i], _Dis[i] = Dis[i];
for (int i = ; i <= tot; i ++)
_h[i] = h[i];
} inline void Restore()
{
tot = _tot;
for (int i = S; i <= T; i ++)
Head[i] = _Head[i];
for (int i = ; i <= _tot; i ++)
h[i] = _h[i];
} inline bool cmp(int u, int v)
{
return Dis[u] < Dis[v];
} inline int dinic(int z, int inflow)
{
if (z == T || !inflow) return inflow;
int ret = inflow, flow;
for (int i = Head[z]; i; i = h[i].next)
{
int d = h[i].node, p = h[i].flow;
if (Dis[d] != Dis[z] + ) continue ;
flow = dinic(d, min(ret, p));
ret -= flow;
h[i].flow -= flow, h[i ^ ].flow += flow;
if (!ret) return inflow;
}
if (ret == inflow) Dis[z] = -;
return inflow - ret;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("3955.in", "r", stdin);
freopen("3955.out", "w", stdout);
#endif scanf("%d%d%d", &n, &m, &c);
S = , T = n + ;
for (int i = ; i <= m; i ++)
{
int u, v, w;
scanf("%d%d%d", &u ,&v, &w);
E[i][] = u, E[i][] = v, E[i][] = w;
addedge(u, v, , w);
addedge(v, u, , w);
}
SPFA();
for (int i = ; i <= c; i ++)
scanf("%d", A + i);
sort(A + , A + c + , cmp);
tot = ;
memset(Head, , sizeof(Head));
for (int i = ; i <= m; i ++)
{
if (Dis[E[i][]] + E[i][] == Dis[E[i][]])
addedge(E[i][], E[i][], , );
if (Dis[E[i][]] + E[i][] == Dis[E[i][]])
addedge(E[i][], E[i][], , );
}
Copy();
int l = , r;
for (; l <= c; l = r + )
{
for (r = l; r < c && _Dis[A[r + ]] == _Dis[A[l]]; r ++) ;
if (r == l) ans ++;
else
{
Restore();
for (int i = l; i <= r; i ++)
addedge(A[i], T, , );
while (SPFA(S))
ans += dinic(S, INF);
}
}
printf("%d\n", ans); #ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return ;
}
3955_Gromah
BZOJ 3955 Surely You Congest 解题报告的更多相关文章
- bzoj 1565 [NOI2009]植物大战僵尸 解题报告
1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2161 Solved: 1000[Submit][Stat ...
- BZOJ 4029 [HEOI 4029] 定价 解题报告
这个题好像也是贪心的感觉.. 我们枚举 $1,5,10,50,100,\dots$ ,找出在 $[l, r]$ 内能整除它们的最小的数. 然后找到其中在荒谬值最小的情况下数值最小的那个数, 就做完了. ...
- BZOJ 3998 [TJOI 2015] 弦论 解题报告
这是一道后缀自动机经典题目. 对于 $t=0$ 的情况:每个节点都代表一个子串,所以我们给每个节点的 $Size$ 都记为 $1$, 对于 $t=1$ 的情况:我们只给 $last$ 节点的 $Siz ...
- BZOJ 3997 [TJOI 2015 组合数学] 解题报告
这个题我脑洞了一个结论: 首先,我们定义满足以下条件的路径为“从右上到左下的路径”: 对于路径上任何不相同的两个点 $(x_1, y_1)$,$(x_2, y_2)$,都有: $x_1\neq x_2 ...
- BZOJ 3996 [TJOI 2015] 线性代数 解题报告
首先,我们可以得到: $$D = \sum_{i=1}^{n}\sum_{j=1}^{n}a_i\times a_j\times b_{i,j} - \sum_{i=1}^{n}a_i\times c ...
- BZOJ 3990 [SDOI 2015] 排序 解题报告
这个题哎呀...细节超级多... 首先,我猜了一个结论.如果有一种排序方案是可行的,假设这个方案是 $S$ . 那么我们把 $S$ 给任意重新排列之后,也必然可以构造出一组合法方案来. 于是我们就可以 ...
- BZOJ 3929 Circle of digits 解题报告
首先,我们可以得到最高位的位数为:\(\lfloor\frac{n+k-1}{n}\rfloor\),记作 \(E\). 然后给这 \(n\) 个长为 \(E\) 的数字排序,后缀数组 \(O((n+ ...
- BZOJ 4145 [AMPPZ2014] The Prices 解题报告
感觉也是一个小清新题.. 我们考虑设立状态 $Dp[i][s]$ 表示考虑了前 $i$ 个商店后,购买状态为 $s$ 的最小花费. 转移的话就枚举每个商店 $i$,首先令: $$Dp[i][s] = ...
- BZOJ 4710 [Jsoi2011]分特产 解题报告
4710 [Jsoi2011]分特产 题意 给定\(n\)个集合,每个集合有相同的\(a_i\)个元素,不同的集合的元素不同.将所有的元素分给\(m\)个不同位置,要求每个位置至少有一个元素,求分配方 ...
随机推荐
- SWT中的布局之-----FormLayout(表格式布局)
表格式(FormLayout类) 表格式布局管理器,通过创建组件各个边的距离来布局组件,和GridLayout一样强大. 用GridLayout与FormLayout都可以实现相同的界面效果,但有时使 ...
- linux基于file的logger
我们可能会遇到这样的问题:即写出的代码可能需要编译成动态连接库并在不同运行环境下运行,而这些运行环境下log的输出方式可能不同,一种运行环境的log方式在另一种运行环境下可能无法输出.而为保证多种运行 ...
- centos vim 中文乱码解决方案
1.安装中文包:yum -y groupinstall chinese-support 2.修改字符编码配置文件 vi /etc/sysconfig/i18n LANGUAGE="zh_ ...
- mysql copy表或表数据常用的语句整理汇总
mysql copy表或表数据常用的语句整理汇总. 假如我们有以下这样一个表: id username password ----------------------------------- 1 a ...
- 跨域方法之CORS
跨域的方法非常之多,如果想了解其中CORS,不要浪费时间,看下面三个就够了 了解CORS https://developer.mozilla.org/en-US/docs/Web/HTTP/Acc ...
- EXT.NET学习笔记(一) 下载配置使用
新公司使用ext.net开发,开始学习该知识: 首先下载ext.net,目前我使用的版本为1.7,该版本免费,基本的功能也够用,使用ext.net进行开发时强烈建议使用VS2015,能便捷的提示,大大 ...
- JAVA访问配置文件总结
一.全局配置的简单 propertie 文件实现 package com.testgs.utils; import java.util.*; import java.io.*; public fina ...
- 为 Date 对象添加 ago 属性
/* * 此处,__defineGetter__与__defineSetter__相当于C#实体中类中的get与set **/ Date.prototype.__defineGetter__('ago ...
- sea.js总结
SeaJS是一个遵循CommonJS规范的JavaScript模块加载框架. 参考以下网址进行详细学习: https://segmentfault.com/a/1190000000357191?pag ...
- 学习C++ Primer 的个人理解(七)
类,后面还有两章是介绍有关于类的内容的.这一张依然只是个概括.但也已经将大致用法介绍完了. 重点如下: 1.成员函数的声明,必须在类的内部. 2.引用const成员函数 我们知道成员函数中有一个名为t ...