首先,我们可以求出源为 $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 解题报告的更多相关文章

  1. bzoj 1565 [NOI2009]植物大战僵尸 解题报告

    1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2161  Solved: 1000[Submit][Stat ...

  2. BZOJ 4029 [HEOI 4029] 定价 解题报告

    这个题好像也是贪心的感觉.. 我们枚举 $1,5,10,50,100,\dots$ ,找出在 $[l, r]$ 内能整除它们的最小的数. 然后找到其中在荒谬值最小的情况下数值最小的那个数, 就做完了. ...

  3. BZOJ 3998 [TJOI 2015] 弦论 解题报告

    这是一道后缀自动机经典题目. 对于 $t=0$ 的情况:每个节点都代表一个子串,所以我们给每个节点的 $Size$ 都记为 $1$, 对于 $t=1$ 的情况:我们只给 $last$ 节点的 $Siz ...

  4. BZOJ 3997 [TJOI 2015 组合数学] 解题报告

    这个题我脑洞了一个结论: 首先,我们定义满足以下条件的路径为“从右上到左下的路径”: 对于路径上任何不相同的两个点 $(x_1, y_1)$,$(x_2, y_2)$,都有: $x_1\neq x_2 ...

  5. 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 ...

  6. BZOJ 3990 [SDOI 2015] 排序 解题报告

    这个题哎呀...细节超级多... 首先,我猜了一个结论.如果有一种排序方案是可行的,假设这个方案是 $S$ . 那么我们把 $S$ 给任意重新排列之后,也必然可以构造出一组合法方案来. 于是我们就可以 ...

  7. BZOJ 3929 Circle of digits 解题报告

    首先,我们可以得到最高位的位数为:\(\lfloor\frac{n+k-1}{n}\rfloor\),记作 \(E\). 然后给这 \(n\) 个长为 \(E\) 的数字排序,后缀数组 \(O((n+ ...

  8. BZOJ 4145 [AMPPZ2014] The Prices 解题报告

    感觉也是一个小清新题.. 我们考虑设立状态 $Dp[i][s]$ 表示考虑了前 $i$ 个商店后,购买状态为 $s$ 的最小花费. 转移的话就枚举每个商店 $i$,首先令: $$Dp[i][s] = ...

  9. BZOJ 4710 [Jsoi2011]分特产 解题报告

    4710 [Jsoi2011]分特产 题意 给定\(n\)个集合,每个集合有相同的\(a_i\)个元素,不同的集合的元素不同.将所有的元素分给\(m\)个不同位置,要求每个位置至少有一个元素,求分配方 ...

随机推荐

  1. bootstrap兼容IE

    这种响应式的布局正是通过CSS3的媒体查询(Media Query)功能实现的,根据不同的分辨率来匹配不同的样式.IE8浏览器并不支持这一优秀的Css3特性,Bootstrap在开发文档中写了如何使用 ...

  2. SpringMVC文件上传 Excle文件 Poi解析 验证 去重 并批量导入 MYSQL数据库

    SpringMVC文件上传 Excle文件 Poi解析并批量导入 MYSQL数据库  /** * 业务需求说明: * 1 批量导入成员 并且 自主创建账号 * 2 校验数据格式 且 重复导入提示 已被 ...

  3. 跨域方法之CORS

    跨域的方法非常之多,如果想了解其中CORS,不要浪费时间,看下面三个就够了 了解CORS   https://developer.mozilla.org/en-US/docs/Web/HTTP/Acc ...

  4. java面板

    import java.awt.Color; import java.awt.Container; import javax.swing.JFrame; import javax.swing.JLab ...

  5. 在ASP中限制同一表单被多次提交

    本文介绍在ASP应用中防止用户在当前会话期间多次提交同一表单的一个简单方法.它主要由四个子程序组成,在较为简单的应用场合,你只要将这些代码放在包含文件中直接引用即可:对于那些较为复杂的环境,我们在文章 ...

  6. Android带头像的用户注册页面

    详细的图文可以到我的百度经验去查看:http://jingyan.baidu.com/article/cd4c2979eda109756e6e60de.html 首先是注册页面的布局: <?xm ...

  7. 你所不知道的Html5那些事(一)

    文章简介:       关于html5相信大家早已经耳熟能详,但是他真正的意义在具体的开发中会有什么作用呢?相对于html,他又有怎样的新的定义与新理念在里面呢?为什么一些专家认为html5完全完成后 ...

  8. JavaScript高级程序设计(十):数组类型

    先导: 访问对象属性使用的都是点表示法.另外,我们还可以使用方括号表示法来访问对象的属性.在使用方括号的时候,应该将要访问的属性以字符串的形式放到方括号中.这两种方法没有什么区别.但是方括号的优点是可 ...

  9. eclipse下的tomcat内存设置大小

    在eclipse中设置,居然可以了, 设置步骤如下: 1.点击eclipse上的debug图标旁边的下拉箭头 2.然后选择Run Configurations, 3.系统弹出设置tomcat配置页面, ...

  10. mybatis学习(一)一个在idea下的实例

    今天总结的是mybatis,首先说mybatis是什么? MyBatis 是一个简化和实现了 Java 数据持久化层(persistence layer)的开源框架,它抽象了大量的 JDBC 冗余代 ...