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$,就不用去跑网络流了。

感觉效果还不错。

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 using namespace std;
  7 typedef long long LL;
  8 #define C 2000 + 5
  9 #define N 50000 + 5
 10 #define M 400000 + 5
 11 #define SIZE 10000000 + 5
 12 #define INF 0x7fffffff
 13
 14 int n, m, c, S, T, tot, _tot, ans;
 15 int A[C];
 16 int Head[N], _Head[N], Inq[N];
 17 int Dis[N], _Dis[N];
 18 int E[M][3];
 19 int q[SIZE];
 20
 21 struct Edge
 22 {
 23     int next, node, flow, w;
 24 }h[M], _h[M];
 25
 26 inline void addedge(int u, int v, int fl, int w)
 27 {
 28     h[++ tot].next = Head[u], Head[u] = tot;
 29     h[tot].node = v, h[tot].flow = fl, h[tot].w = w;
 30     h[++ tot].next = Head[v], Head[v] = tot;
 31     h[tot].node = u, h[tot].flow = 0, h[tot].w = w;
 32 }
 33
 34 inline bool SPFA(int S)
 35 {
 36     for (int i = S; i <= T; i ++)
 37         Dis[i] = INF, Inq[i] = 0;
 38     int l = 1, r = 1;
 39     Dis[S] = 0, q[1] = S, Inq[S] = 1;
 40     while (l <= r)
 41     {
 42         int z = q[l ++];
 43         Inq[z] = 0;
 44         for (int i = Head[z]; i; i = h[i].next)
 45         {
 46             int d = h[i].node, p = h[i].flow, w = h[i].w;
 47             if (!p) continue ;
 48             if (Dis[d] > Dis[z] + w)
 49             {
 50                 Dis[d] = Dis[z] + w;
 51                 if (!Inq[d])
 52                 {
 53                     q[++ r] = d;
 54                     Inq[d] = r;
 55                 }
 56             }
 57             if (Inq[d] && Dis[d] < Dis[q[l]])
 58             {
 59                 int u = Inq[d], v = q[l];
 60                 q[l] = d, q[u] = v;
 61                 Inq[d] = l, Inq[v] = u;
 62             }
 63         }
 64     }
 65     return Dis[T] != INF;
 66 }
 67
 68 inline void Copy()
 69 {
 70     _tot = tot;
 71     for (int i = S; i <= T; i ++)
 72         _Head[i] = Head[i], _Dis[i] = Dis[i];
 73     for (int i = 2; i <= tot; i ++)
 74         _h[i] = h[i];
 75 }
 76
 77 inline void Restore()
 78 {
 79     tot = _tot;
 80     for (int i = S; i <= T; i ++)
 81         Head[i] = _Head[i];
 82     for (int i = 2; i <= _tot; i ++)
 83         h[i] = _h[i];
 84 }
 85
 86 inline bool cmp(int u, int v)
 87 {
 88     return Dis[u] < Dis[v];
 89 }
 90
 91 inline int dinic(int z, int inflow)
 92 {
 93     if (z == T || !inflow) return inflow;
 94     int ret = inflow, flow;
 95     for (int i = Head[z]; i; i = h[i].next)
 96     {
 97         int d = h[i].node, p = h[i].flow;
 98         if (Dis[d] != Dis[z] + 1) continue ;
 99         flow = dinic(d, min(ret, p));
100         ret -= flow;
101         h[i].flow -= flow, h[i ^ 1].flow += flow;
102         if (!ret) return inflow;
103     }
104     if (ret == inflow) Dis[z] = -1;
105     return inflow - ret;
106 }
107
108 int main()
109 {
110     #ifndef ONLINE_JUDGE
111         freopen("3955.in", "r", stdin);
112         freopen("3955.out", "w", stdout);
113     #endif
114
115     scanf("%d%d%d", &n, &m, &c);
116     S = 1, T = n + 1;
117     for (int i = 1; i <= m; i ++)
118     {
119         int u, v, w;
120         scanf("%d%d%d", &u ,&v, &w);
121         E[i][0] = u, E[i][1] = v, E[i][2] = w;
122         addedge(u, v, 1, w);
123         addedge(v, u, 1, w);
124     }
125     SPFA(1);
126     for (int i = 1; i <= c; i ++)
127         scanf("%d", A + i);
128     sort(A + 1, A + c + 1, cmp);
129     tot = 1;
130     memset(Head, 0, sizeof(Head));
131     for (int i = 1; i <= m; i ++)
132     {
133         if (Dis[E[i][0]] + E[i][2] == Dis[E[i][1]])
134             addedge(E[i][0], E[i][1], 1, 1);
135         if (Dis[E[i][1]] + E[i][2] == Dis[E[i][0]])
136             addedge(E[i][1], E[i][0], 1, 1);
137     }
138     Copy();
139     int l = 1, r;
140     for (; l <= c; l = r + 1)
141     {
142         for (r = l; r < c && _Dis[A[r + 1]] == _Dis[A[l]]; r ++) ;
143         if (r == l) ans ++;
144         else
145         {
146             Restore();
147             for (int i = l; i <= r; i ++)
148                 addedge(A[i], T, 1, 1);
149             while (SPFA(S))
150                 ans += dinic(S, INF);
151         }
152     }
153     printf("%d\n", ans);
154
155     #ifndef ONLINE_JUDGE
156         fclose(stdin);
157         fclose(stdout);
158     #endif
159     return 0;
160 }

3955_Gromah

时间: 2024-11-01 16:15:33

BZOJ 3955 Surely You Congest 解题报告的相关文章

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

这个题哎呀...细节超级多... 首先,我猜了一个结论.如果有一种排序方案是可行的,假设这个方案是 $S$ . 那么我们把 $S$ 给任意重新排列之后,也必然可以构造出一组合法方案来. 于是我们就可以 $O(2^n)$ 枚举每个操作进不进行,再去判断,如果可行就 $ans$ += $|S|!$. 然而怎么判断呢? 我们按照操作种类从小到大操作. 假设我们现在在决策第 $i$ 种操作并且保证之前之后不需要进行种类编号 $< i$ 的操作. 那么我们只考虑那些位置在 $2^i+1$ 的位置的那些数.

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_i$$ 那么是不是就相当于这样的问题: 有 $n$ 个物品,你可以选择一些物品出来,如果同时选了 $i,j$ 两个物品那么就有 $b_{i,j}$ 的收益,然而每一个物品都有一个代价 $c_i$,求最大收益. 这是经典的最小割模型: 连边 $S\to Dot(i,j)$,流量为 $b_{i,j}$

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

这个题我脑洞了一个结论: 首先,我们定义满足以下条件的路径为“从右上到左下的路径”: 对于路径上任何不相同的两个点 $(x_1, y_1)$,$(x_2, y_2)$,都有: $x_1\neq x_2, y_1\neq y_2$ 若 $x_1 > x_2$,则有 $y_1 < y_2$:否则当 $x_1 < x_2$ 时, $y_1 > y_2$. 然后我们找到所有从右上到左下的路径,其中路径的权值和最大的那条路径的权值和就是答案了. 然后我们就可以用 Dp 解决问题了. 我们可以

BZOJ 4145 [AMPPZ2014] The Prices 解题报告

感觉也是一个小清新题.. 我们考虑设立状态 $Dp[i][s]$ 表示考虑了前 $i$ 个商店后,购买状态为 $s$ 的最小花费. 转移的话就枚举每个商店 $i$,首先令: $$Dp[i][s] = Dp[i - 1][s] + D[i]$$ 这个过程表示到达这个商店. 然后枚举每个状态 $s$,然后枚举每个不在 $s$ 里的物品 $j$,令: $$Dp[i][s + \{j\}] = min(Dp[i][s + \{j\}], Dp[i][s] + Cost[i][j])$$ 这个过程就相当于

BZOJ 1051 最受欢迎的牛 解题报告

题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4438  Solved: 2353[Submit][Status][Discuss] Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这 种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎.你的任务是求出有多少头 牛被所有的牛

Poi 2014 解题报告( 1 - 4 ,6 )

撸了一下Poi 2014 ,看了一下网上题解不多,所以决定写一下.有的题应该是数据不强水过去了,等北京回来在写一下复杂度比较靠谱的代码 o(╯□╰)o 第一题: 题意是给定一个长度不大于1000000,只包括p和j的串,求一个最长的子串,要求子串任何一个前缀和后缀都满足p的数量不少于j的数量. 首先把p当做1,把j当做0,算出前缀和 sum[] ,原来的问题就转化为求一个最长区间 [l,r] ,使得任意的i∈[l,r],都有 sum[i] - sum[l-1] >= 0 并且 sum[r] -

【模拟题(电子科大MaxKU)】解题报告

目录: 1:一道简单题[树形问题](Bzoj 1827 奶牛大集会) 2:一道更简单题[矩阵乘法][快速幂] 3:最简单题[技巧] 话说这些题目的名字也是够了.... 题目: 1.一道简单题 时间1s 题目描述 Bessie正在计划一年一度的奶牛大集会,来自全国各地的奶牛将来参加这一次集会.当然,她会选择最方便的地点来举办这次集会.每个奶牛居住在 N(1<=N<=100,000) 个农场中的一个,这些农场由N-1条道路连接,并且从任意一个农场都能够到达另外一个农场.道路i连接农场A_i和B_i

解题报告 之 POJ3057 Evacuation

解题报告 之 POJ3057 Evacuation Description Fires can be disastrous, especially when a fire breaks out in a room that is completely filled with people. Rooms usually have a couple of exits and emergency exits, but with everyone rushing out at the same time

hdu 1541 Stars 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1541 题目意思:有 N 颗星星,每颗星星都有各自的等级.给出每颗星星的坐标(x, y),它的等级由所有比它低层(或者同层)的或者在它左手边的星星数决定.计算出每个等级(0 ~ n-1)的星星各有多少颗. 我只能说,题目换了一下就不会变通了,泪~~~~ 星星的分布是不是很像树状数组呢~~~没错,就是树状数组题来滴! 按照题目输入,当前星星与后面的星星没有关系.所以只要把 x 之前的横坐标加起来就可以了