电子科技大学2022暑假前集训 图论专题
题解
A
跑 \(n-1\) 次最大流,每次以 \(1\) 为源点,\(i\) 为汇点。然后就过了((PS:此题实际上是 Stoer-Wagner 模板题)
B
首先肯定是跑最小生成树。那么每次合并两个集合时,考虑启发式合并,将小集合中每个点取出,然后在大集合中计算与取出的点点权之差小于 \(L\) 的点的数目,乘上边权加到答案里。考虑手写平衡树或者 pb_ds 维护集合中点权在一个区间内的点的数目。注意特判 \(L=0\) 的情况,如果出现两个点点权相同会被计算两次。
C
显然对角线如果和管道方向相同就连 \(0\) 边,不同就连 \(1\) 边。从一个结点开始 BFS,每到达一个未访问过结点,利用 DFS 将距离为 \(0\) 的连通块全部标记为 vis 并入队。
D
考虑矩阵快速幂,每转移到 \(d_i\) 次将一些边加入邻接矩阵。最后 Bitset 优化布尔矩阵快速幂。
E
点双缩点,将点双和割点都看作新图中的点来建图。注意如果询问的点对中某一个为割点,则必须将这一点看作对应新图中的割点形成的点。
F
差分约束裸题。由 \(v\) 向 \(u\) 连一条权值为 \(w\) 的边,然后跑 SPFA,若有负环则说明无解。
G
单独计算每一对 \(A_i\) 和 \(B_j\) 匹配之后得到的期望得分,问题转化为最大权匹配,利用 KM 算法解决。
H
奇数连通块必然可拆成一个奇数连通块和一个偶数连通块,奇数连通块再拆,从而最后一定拆出一个孤立点,反过来一个奇数连通块要且只要拆掉一个点。考虑拆掉哪个点。如果一个点拆掉之后形成的所有联通块为偶数,则可拆,若存在奇数,则必须再拆点,使得拆点数量多于一个,不符合结论。而只有割点会产生多个连通块,因此 DCC 缩点之后在树上跑 DP,求出与一个割点相连的连通块是否存在奇数连通块。最后按点权从小到大的顺序枚举点,若该点可删且所在连通块为奇数连通块,则删除该点并将连通块标记为偶数连通块。
I
2-SAT 裸题。将一个点拆成两个点 \(u_0\) \(u_1\),令 \(u\) 向 \(v\) 连边表示若 \(u\) 则 \(v\)。那么,例如一组约束条件为 \(u\) \(0\) \(v\) \(1\),则 \(u_1\) 向 \(v_1\) 连边,\(v_0\) 向 \(u_0\) 连边。然后跑强连通分量,如果 \(u_0\) 和 \(u_1\) 在同一个强连通分量中,说明 \(u\) 同时为 \(0\) 和 \(1\),自相矛盾,因此无解。否则,若所有点都满足拆成的两点不在同一强连通分量中,则说明是有解的。
J
割点、割边、点双个数:跑一遍 Tarjan。
点双包含的边数的最大值:观察到数据范围小,因此我们可以暴力枚举所有边,然后将每条边的两个端点所属的点双取交集,交集必然只有一个点双,该点双就是该边所属的点双。
K
给出数据是一棵树。先钦定一点为根跑 DFS,跑出每点的深度。对于每个询问 \(u\),\(v\) 求 LCA,则答案就是 \(dep_u+dep_v-dep_{lca}\)。
L
在所有最小生成树中,同一边权的边个数一定相同,且形成的连通块也相同。基于这一点,我们先跑出一个最小生成树,然后枚举每一边权的边。对于除该边权以外的边,若它在最小生成树上,则将该边连接的两点缩点。最后利用矩阵树定理即可计算出某一边权的边对应的生成树数量。将所有边权的生成树数量相乘即为答案。
M
\(k\) 短路模板题。
在反向图上,以 \(t\) 为根建立最短路径树。则如果我们钦定一条非最短路径边 \((u,v)\) 必须被使用,则路径长度增加 \(dis_v+w-dis_u\)。
于是我们设计一个状态四元组 \(\{u,v,w,e\}\),其中 \(u\) 表示倒数第二条钦定边的终点,\(v\) 表示倒数第一条钦定边的终点,\(w\) 表示该状态方案的路径长度,\(e\) 表示最后一条边。那么从该状态扩展,可以扩展到两个状态:
-
将 \(e\) 替换为一条另一条以 \(u\) 的祖先为起点且恰劣于 \(e\) 的边,同时 \(v\) 会发生改变;
-
增加一条以 \(v\) 的祖先为起点的边,同时 \(u\) 变为 \(v\),\(v\)、\(e\) 变为新值。
将状态放入以 \(w\) 为关键字的优先队列,每次取出队头进行扩展,扩展 \(k\) 次就得到了 \(k\) 短路。
N
最小直径生成树模板题。
定义图的绝对中心为到所有点的最短距离的最大值最小的位置,这个位置可能在点上,也可能在一条边上。
那么,首先用 Floyd 求出两两点之间的最短路。设 \(d(i,j)\) 表示 \(i\) 与 \(j\) 之间的最短路,\(rk(i,k)\) 表示所有点中到 \(i\) 距离第 \(k\) 远的点。
如果绝对中心在点上,则答案就是 \(\min_i\{d(i,rk(i,n))×2\}\)。
如果绝对中心在一条边 \((u,v)\) 上,我们不妨 “枚举” \((u,v)\) 上的每一个点 \(c\),设 \(c\) 到 \(u\) 的距离为 \(x\),则 \(c\) 到 \(v\) 的距离为 \(w-x\)。那么 \(c\) 到某点 \(i\) 的距离就是 \(\min_x\{d(u,i)+x,d(v,i)+w-x\}\)。随着 \(c\) 从 \(u\) 移动到 \(v\),\(c\) 到一点 \(i\) 的距离将会先上升后下降,形成一个单峰折线。对于所有 \(i\) 对应折线的上壳,其最低点对应的 \(c\) 就是该边上绝对中心的可能位置。找出该位置更新答案即可。
O
最短路裸题。跑一遍 Dijkstra 即可。
P
从左上角生成一颗到所有特殊格的最短路径生成树,钦定回路包含该生成树即可。
Q
当选择一个点加入生成树时,在线段树上用该点更新到达不在生成树中的点的最短距离。
更具体地,开两颗线段树,一颗维护从某个生成树上的点 \(u\) 向左走到达每个点 \(v\) \((v<u)\) 的最短距离。那么显然 \(dist_{u,v}=(A_u+uD)+(A_v-vD)\)。线段树上维护两个值,一个是终点 \(v\) 的权值 \(A_v-vD\),一个是起点 \(u\) 的权值 \(A_u+uD\)。由于在起点中我们只会选择权值最小的那个,而起点权值是对一个前缀区间取 \(\min\),这使得我们最多会产生 \(n\) 个区间,使得这些区间两两起点权值不同。对于每个这样的区间,取其中终点权值最小的点即可。
另一颗线段树同理。
R
最小树形图裸题,使用朱刘算法解决。具体流程是,每次对于每一点都选择到达该点的边中权值最小的边,然后将图中的环缩点,再不断执行这一流程。
S
一般图最大匹配裸题,使用带花树算法解决。
带花树算法:DFS 时顺便黑白染色,于是第二次访问某节点时可以知道所成的环是奇环还是偶环。对于奇环,必然可以让其中任意一个点向外匹配,其他形成完美匹配,于是缩点即可。不停缩点直到不存在奇环,然后跑普通二分图匹配。
T
DAG 上的最少路径覆盖裸题,等价于二分图最大匹配问题。
具体而言,每当我们选中一条边,我们的路径条数就会减 1。因此我们要最大化选中的路径条数。如果把从 \(u\) 到 \(v\) 的边看作匹配 \((u,v)\),那么就转化为二分图最大匹配问题。
代码
A
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 301, M = 1001;
int n, m, s, t, head[N], nxt[M << 1], to[M << 1], c[M << 1], tmp[M << 1], eid = 2;
inline void addedge(int u, int v, int w){
to[eid] = v;
c[eid] = w;
nxt[eid] = head[u];
head[u] = eid++;
}
int d[N], q[N], l, r;
long long dfs(int i, long long f = 0x7fffffffffffffff){
if(i == t) return f;
long long ans = 0;
for(int e = head[i]; f && e; e = nxt[e]) if(d[to[e]] > d[i] && c[e]){
int ret = dfs(to[e], min(f, (long long) c[e]));
f -= ret;
c[e] -= ret;
c[e ^ 1] += ret;
ans += ret;
}
if(!ans) d[i] = 0;
return ans;
}
long long solve(){
memcpy(c, tmp, sizeof(tmp));
long long ans = 0;
while(true){
memset(d + 1, 0, sizeof(int) * n);
d[s] = 1;
l = r = 0;
q[r++] = s;
while(l != r){
int i = q[l++];
for(int e = head[i]; e; e = nxt[e]) if(c[e] && !d[to[e]]){
d[to[e]] = d[i] + 1;
q[r++] = to[e];
}
}
if(!d[t]) break;
ans += dfs(s);
}
return ans;
}
int u, v, w;
long long ans = 0x7fffffffffffffff;
int main(){
scanf("%d%d", &n, &m);
s = 1;
while(m--){
scanf("%d%d", &u, &v);
addedge(u, v, 1);
addedge(v, u, 1);
}
memcpy(tmp, c, sizeof(c));
for (t = 2; t <= n; t++)
ans = min(ans, solve());
printf("%lld", ans);
return 0;
}
B
#include <cstdio>
#include <algorithm>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
const int N = 2e5 + 1, M = 5e5 + 1;
struct node{
int c, id;
node(int _c, int _id) : c(_c), id(_id){}
bool operator<(const node &b) const{
return c != b.c ? c > b.c : id > b.id;
}
};
tree<node, null_type, less<node>, rb_tree_tag, tree_order_statistics_node_update> tr[N];
int n, m, k, c, fa[N];
int find(int x){
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
struct edge{
int u, v, w;
edge(){}
edge(int _u, int _v, int _w) : u(_u), v(_v), w(_w){}
bool operator<(const edge &b) const{
return w < b.w;
}
}e[M];
long long ans;
int main(){
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; i++){
fa[i] = i;
scanf("%d", &c);
tr[i].insert(node(c, i));
}
for (int i = 1; i <= m; i++)
scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
sort(e + 1, e + 1 + m);
for (int i = 1; i <= m; i++){
int u = find(e[i].u), v = find(e[i].v);
if(u != v){
if(tr[u].size() < tr[v].size())
swap(u, v);
if(k)
for(auto nd : tr[v])
ans += 1ll * e[i].w * (tr[u].order_of_key(node(nd.c + k, 0)) + tr[u].size() - tr[u].order_of_key(node(nd.c - k, n + 1)));
else
ans += 1ll * e[i].w * tr[v].size() * tr[u].size();
for(auto nd : tr[v])
tr[u].insert(nd);
fa[v] = u;
}
}
printf("%lld", ans);
return 0;
}
C
#include <cstdio>
#include <utility>
#include <queue>
#include <cstring>
using namespace std;
const int N = 502, X[4] = {1, 1, -1, -1}, Y[4] = {1, -1, -1, 1}, PX[4] = {1, 1, 0, 0}, PY[4] = {1, 0, 0, 1};
typedef pair<int, int> duo;
int n, m;
int dist[N][N];
char s[N][N];
bool legal(int x, int y){
return x >= 0 && y >= 0 && x <= n && y <= m;
}
queue<duo> q;
void dfs(int x, int y){
q.push(duo(x, y));
for (int i = 0; i < 4; i++){
int nx = x + X[i];
int ny = y + Y[i];
if(legal(nx, ny) && dist[nx][ny] == -1 && (s[x + PX[i]][y + PY[i]] == '/') == (i & 1)){
dist[nx][ny] = dist[x][y];
dfs(nx, ny);
}
}
}
int main(){
memset(dist, -1, sizeof(dist));
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%s", s[i] + 1);
dist[0][0] = 0;
dfs(0, 0);
while(!q.empty()){
int x = q.front().first;
int y = q.front().second;
q.pop();
for (int i = 0; i < 4; i++){
int nx = x + X[i];
int ny = y + Y[i];
if(legal(nx, ny) && dist[nx][ny] == -1 && (s[x + PX[i]][y + PY[i]] == '/') != (i & 1)){
dist[nx][ny] = dist[x][y] + 1;
dfs(nx, ny);
}
}
}
if(dist[n][m] == -1)
puts("NO SOLUTION");
else
printf("%d", dist[n][m]);
return 0;
}
D
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <bitset>
using namespace std;
const int N = 181;
int n, m, c, u, v, w, d[N], lv[N][N], dist[N];
bitset<N> vec, tmpvec, trans[N], base[N], res[N], tmp[N], flip[N];
void matmul(bitset<N> a[N], bitset<N> b[N]){
for (int i = 1; i <= n; i++)
tmp[i].reset();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
flip[i][j] = b[j][i];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
tmp[i][j] = (a[i] & flip[j]).any();
for (int i = 1; i <= n; i++)
a[i] = tmp[i];
}
void fpow(bitset<N> res[N], bitset<N> base[N], int t){
if(!t){
for (int i = 1; i <= n; i++)
res[i][i] = 1;
return;
}
while(t){
if(t & 1)
matmul(res, base);
matmul(base, base);
t >>= 1;
}
}
int ans = 0x7fffffff;
queue<int> q;
int main(){
memset(lv, 0x3f, sizeof(lv));
scanf("%d%d%d", &n, &m, &c);
while(m--){
scanf("%d%d%d", &u, &v, &w);
lv[u][v] = min(lv[u][v], w);
}
vec[1] = 1;
for (int i = 1; i <= c; i++){
scanf("%d", &d[i]);
for (int i = 1; i <= n; i++){
res[i].reset();
res[i][i] = 1;
base[i] = trans[i];
}
fpow(res, base, d[i] - d[i - 1]);
tmpvec.reset();
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
tmpvec[j] = tmpvec[j] | (vec[k] & res[k][j]);
vec = tmpvec;
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
if (lv[j][k] == i)
trans[j][k] = 1;
for (int i = 1; i <= n; i++){
if(vec[i]){
dist[i] = 0;
q.push(i);
}else
dist[i] = 0x3f3f3f3f;
}
while(!q.empty()){
int i = q.front();
q.pop();
for (int j = 1; j <= n; j++)
if(trans[i][j] && dist[j] > dist[i] + 1){
dist[j] = dist[i] + 1;
q.push(j);
}
}
ans = min(ans, d[i] + dist[n]);
}
if(ans >= 0x3f3f3f3f)
puts("Impossible");
else
printf("%d", ans);
return 0;
}
E
#include <cstdio>
#include <vector>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 1, L = 20;
int n, m, q, u, v, w[N];
vector<int> g[N];
int fa[N], dfn[N], low[N], idx, stk[N], top;
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
bool cut[N];
vector<int> dcc[N], belong[N];
int dcccnt;
void tarjan(int u){
if(u == 1 && g[u].empty()){
dcc[++dcccnt].push_back(1);
return;
}
dfn[u] = low[u] = ++idx;
stk[++top] = u;
int cnt = 0;
for(auto v : g[u]){
if(!dfn[v]){
cnt++;
tarjan(v);
low[u] = min(low[u], low[v]);
if(dfn[u] <= low[v]){
dcccnt++;
if(u != 1 || cnt > 1)
cut[u] = true;
int x;
do{
x = stk[top--];
dcc[dcccnt].push_back(x);
belong[x].push_back(dcccnt);
} while (x != v);
dcc[dcccnt].push_back(u);
belong[u].push_back(dcccnt);
}
}
else low[u] = min(low[u], dfn[v]);
}
}
int dccans[N], ans[N];
bool vis[N];
bool visdcc[N];
void dfs(int u){
vector<int> vec;
for(auto id : belong[u]) if(!visdcc[id]){
for(auto v : dcc[id]) if(!vis[v]){
vis[v] = true;
ans[v] = min(ans[u], dccans[id]);
vec.push_back(v);
}
}
while(!vec.empty()){
dfs(vec.back());
vec.pop_back();
}
}
int main(){
memset(dccans, 0x7f, sizeof(ans));
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++)
fa[i] = i;
while (m--){
scanf("%d%d", &u, &v);
u = -u, v = -v;
g[u].push_back(v);
g[v].push_back(u);
}
for (int i = 1; i <= n; i++)
scanf("%d", &w[i]);
tarjan(1);
for (int i = 1; i <= dcccnt; i++){
for(auto x : dcc[i])
dccans[i] = min(dccans[i], w[x]);
}
vis[1] = true;
ans[1] = w[1];
for(auto id : belong[1]){
visdcc[id] = true;
for(auto x : dcc[id]) if(x != 1){
ans[x] = dccans[id];
vis[x] = true;
}
}
for(auto id : belong[1])
for(auto x : dcc[id])
dfs(x);
ans[1] = w[1];
dfs(1);
while(q--){
scanf("%d", &u);
printf("%d\n", ans[u]);
}
return 0;
}
F
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N = 5e3 + 1;
int n, m, u, v, w, head[N], nxt[N], val[N], to[N], eid = 1;
void addedge(int u, int v, int w){
to[eid] = v;
val[eid] = w;
nxt[eid] = head[u];
head[u] = eid++;
}
int cnt[N];
long long dist[N];
queue<int> q;
int main(){
scanf("%d%d", &n, &m);
while(m--){
scanf("%d%d%d", &u, &v, &w);
addedge(v, u, w);
}
bool ans = true;
for(int i = 1; i <= n; i++)
q.push(i);
while(!q.empty()){
int u = q.front();
q.pop();
cnt[u]++;
if(cnt[u] >= n){
ans = false;
break;
}
for(int e = head[u]; e; e = nxt[e]){
if(dist[to[e]] > dist[u] + val[e]){
dist[to[e]] = dist[u] + val[e];
q.push(to[e]);
}
}
}
puts(ans ? "YES" : "NO");
return 0;
}
G
#include <algorithm>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 405;
int w[N][N];
int lx[N], ly[N];
int rmatch[N];
bool lvis[N], rvis[N];
int slack[N];
bool find(int i, int n) {
lvis[i] = true;
for (int j = 1; j <= n; j++)
if (lx[i] + ly[j] == w[i][j] && !rvis[j]) {
rvis[j] = true;
if (!rmatch[j] || find(rmatch[j], n)) {
rmatch[j] = i;
return true;
}
} else {
slack[j] = min(slack[j], lx[i] + ly[j] - w[i][j]);
}
return false;
}
void update(int n) {
int dt = INF;
for (int j = 1; j <= n; j++)
if (!rvis[j]) dt = min(dt, slack[j]);
for (int i = 1; i <= n; i++) {
if (lvis[i]) lx[i] -= dt;
if (rvis[i])
ly[i] += dt;
else
slack[i] -= dt;
}
}
int KM(int n) {
for (int i = 1; i <= n; i++) {
rmatch[i] = lx[i] = ly[i] = 0;
for (int j = 1; j <= n; j++) {
lx[i] = max(lx[i], w[i][j]);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
slack[j] = INF;
}
while (true) {
for (int j = 1; j <= n; j++) {
lvis[j] = rvis[j] = false;
}
if (find(i, n))
break;
else
update(n);
}
}
int res = 0;
for (int i = 1; i <= n; i++) {
res += lx[i] + ly[i];
}
return res;
}
struct node{
long long c;
int w;
node(){}
node(long long _c) : c(_c){}
bool operator<(const node &b) const{
return c < b.c;
}
}nd[N];
long long a[N], b[N];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%lld", &nd[i].c);
for (int i = 1; i <= n; i++)
scanf("%d", &nd[i].w);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
for (int i = 1; i <= n; i++)
scanf("%lld", &b[i]);
sort(nd + 1, nd + 1 + n);
for (int i = 2; i <= n; i++)
nd[i].w += nd[i - 1].w;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
w[i][j] = (lower_bound(nd + 1, nd + 1 + n, node(a[i] + b[j])) - 1)->w;
printf("%d", KM(n));
return 0;
}
H
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
using namespace std;
const int N = 1e6 + 1;
typedef pair<int, int> duo;
int t, n, m, u, v, cnt[N];
vector<int> g[N];
int fa[N], dfn[N], low[N], idx, stk[N], top;
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
bool cut[N];
vector<int> dcc[N], belong[N];
int root, dcccnt;
void tarjan(int u){
if(u == root && g[u].empty()){
dcc[++dcccnt].push_back(1);
return;
}
dfn[u] = low[u] = ++idx;
stk[++top] = u;
int cnt = 0;
for(auto v : g[u]){
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u], low[v]);
if(dfn[u] <= low[v]){
cnt++;
dcccnt++;
if(u != root || cnt > 1)
cut[u] = true;
int x;
do{
x = stk[top--];
dcc[dcccnt].push_back(x);
belong[x].push_back(dcccnt);
} while (x != v);
dcc[dcccnt].push_back(u);
belong[u].push_back(dcccnt);
}
}
else low[u] = min(low[u], dfn[v]);
}
}
int sz[N], szdcc[N];
bool candel[N], vis[N];
void dfs(int i, int from){
vis[i] = true;
sz[i] = 1;
for(auto id : belong[i]) if(id != from){
szdcc[id] = dcc[id].size() - 1;
for(auto x : dcc[id]) if(cut[x] && x != i){
dfs(x, id);
szdcc[id] += sz[x] - 1;
}
if(szdcc[id] % 2 == 1)
candel[i] = false;
sz[i] += szdcc[id];
}
if((cnt[find(i)] - sz[i]) % 2 == 1)
candel[i] = false;
}
duo vert[N];
int main(){
// freopen("in.txt", "r", stdin);
// freopen("std.txt", "w", stdout);
scanf("%d", &t);
while(t--){
for(int i = 1; i <= dcccnt; i++)
dcc[i].clear();
dcccnt = 0;
idx = 0;
top = 0;
long long ans = 0;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++){
vis[i] = false;
g[i].clear();
cut[i] = false;
belong[i].clear();
dfn[i] = low[i] = 0;
scanf("%d", &vert[i].first);
vert[i].second = i;
ans += vert[i].first;
fa[i] = i;
cnt[i] = 1;
candel[i] = true;
}
while(m--){
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
u = find(u), v = find(v);
if(u != v){
// printf("union %d %d\n", u, v);
cnt[u] += cnt[v];
fa[v] = u;
}
}
for(int i = 1; i <= n; i++) if(!dfn[i]){
root = i;
tarjan(i);
}
for (int i = 1; i <= n; i++) if(cut[i] && !vis[i]){
// printf("dfs %d\n", i);
dfs(i, 0);
}
sort(vert + 1, vert + 1 + n);
for (int i = 1; i <= n; i++)
if(candel[vert[i].second]){
int f = find(vert[i].second);
// printf("f %d %d\n", vert[i].second, f);
if(cnt[f] % 2 == 1){
ans -= vert[i].first * 2;
// printf("-= %d\n", vert[i].first);
cnt[f] = 0;
}
}
// for (int i = 1; i <= dcccnt; i++){
// printf("dcc %d: ", i);
// for (auto x : dcc[i])
// printf("%d ", x);
// putchar('\n');
// }
// for (int i = 1; i <= n; i++)
// printf("%d ", candel[i]);
// putchar('\n');
printf("%lld\n", ans);
}
return 0;
}
I
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1e6 + 1;
int n, m, u, v, x, y, head[N << 1], nxt[N << 1], to[N << 1], eid = 1;
void addedge(int u, int v){
to[eid] = v;
nxt[eid] = head[u];
head[u] = eid++;
}
int dfn[N << 1], low[N << 1], idx, stk[N << 1], top;
bool ins[N << 1];
int scccnt, belong[N << 1];
void tarjan(int i){
dfn[i] = low[i] = ++idx;
stk[++top] = i;
ins[i] = true;
for(int e = head[i]; e; e = nxt[e]){
if(!dfn[to[e]]){
tarjan(to[e]);
low[i] = min(low[i], low[to[e]]);
}else if(ins[to[e]])
low[i] = min(low[i], dfn[to[e]]);
}
if(low[i] == dfn[i]){
scccnt++;
while(stk[top] != i){
belong[stk[top]] = scccnt;
ins[stk[top]] = false;
top--;
}
belong[i] = scccnt;
ins[i] = false;
top--;
}
}
int main(){
scanf("%d%d", &n, &m);
while(m--){
scanf("%d%d%d%d", &u, &x, &v, &y);
addedge(u + n * x, v + n * !y);
addedge(v + n * y, u + n * !x);
}
for(int i = 1; i <= 2 * n; i++)
if(!dfn[i])
tarjan(i);
for(int i = 1; i <= n; i++)
if(belong[i] == belong[i + n]){
puts("NO");
return 0;
}
puts("YES");
// for(int i = 1; i <= n; i++)
// printf("%d ", belong[i] < belong[i + n]);
return 0;
}
J
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N = 1001, M = N * (N - 1);
int n, m, u, v, head[N], nxt[M], to[M], eid = 2, ans[4];
bool cutedge[M];
void addedge(int u, int v){
to[eid] = v;
nxt[eid] = head[u];
head[u] = eid++;
}
int dfn[N], low[N], idx;
void bridge(int u, int pre){
low[u] = dfn[u] = ++idx;
for (int e = head[u]; e; e = nxt[e])
if((e >> 1) != pre){
int v = to[e];
if(!dfn[v]){
bridge(v, e >> 1);
low[u] = min(low[u], low[v]);
if(low[v] > dfn[u])
cutedge[e >> 1] = 1;
}else
low[u] = min(low[u], dfn[v]);
}
}
bool cut[N];
int root, stk[N], top, dcccnt;
vector<int> dcc[N], belong[N];
void tarjan(int u, int pre){
dfn[u] = low[u] = ++idx;
stk[++top] = u;
int cnt = 0;
for (int e = head[u]; e; e = nxt[e]){
int v = to[e];
if(!dfn[v]){
cnt++;
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(dfn[u] <= low[v]){
dcccnt++;
if(u != root || cnt > 1)
cut[u] = true;
int x;
do{
x = stk[top--];
dcc[dcccnt].push_back(x);
belong[x].push_back(dcccnt);
} while (x != v);
dcc[dcccnt].push_back(u);
belong[u].push_back(dcccnt);
}
}
else if(v != pre)
low[u] = min(low[u], dfn[v]);
}
}
int edgecnt[N];
bool cover[N];
int main(){
scanf("%d%d", &n, &m);
while(m--){
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
idx = 0;
memset(dfn, 0, sizeof(dfn));
for (int i = 1; i <= n; i++)
if(!dfn[i])
bridge(i, 0);
idx = 0;
memset(dfn, 0, sizeof(dfn));
for (root = 1; root <= n; root++)
if(!dfn[root])
tarjan(root, 0);
for (int i = 1; i <= n; i++)
ans[0] += cut[i];
for (int i = 1; i < eid / 2; i++)
ans[1] += cutedge[i];
ans[2] = dcccnt;
for (int u = 1; u <= n; u++){
for (int e = head[u]; e; e = nxt[e]){
int v = to[e];
memset(cover, 0, sizeof(cover));
for(int id : belong[u])
cover[id] = true;
for(int id : belong[v])
if(cover[id]){
edgecnt[id]++;
break;
}
}
}
for (int i = 1; i <= dcccnt; i++)
ans[3] = max(ans[3], edgecnt[i]);
printf("%d %d %d %d", ans[0], ans[1], ans[2], ans[3] / 2);
return 0;
}
K
#include <cstdio>
#include <vector>
using namespace std;
const int N = 5e5 + 1;
int n, q, u, v, head[N], nxt[N << 1], to[N << 1], eid = 1;
void addedge(int u, int v){
to[eid] = v;
nxt[eid] = head[u];
head[u] = eid++;
}
struct node{
int v, id;
node(int _v, int _id) : v(_v), id(_id){}
};
int ans[N];
vector<node> qry[N];
int fa[N], dep[N];
int find(int x){
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void dfs(int i, int from){
for(auto nd : qry[i]){
if(!ans[nd.id])
ans[nd.id] = -1;
else{
int lca = find(nd.v);
ans[nd.id] = dep[i] - dep[lca] + dep[nd.v] - dep[lca];
}
}
for (int e = head[i]; e; e = nxt[e]) if(to[e] != from){
dep[to[e]] = dep[i] + 1;
dfs(to[e], i);
}
fa[i] = from;
}
int main(){
scanf("%d%d", &n, &q);
for (int i = 1; i < n; i++){
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
for (int i = 1; i <= q; i++){
scanf("%d%d", &u, &v);
qry[u].push_back(node(v, i));
qry[v].push_back(node(u, i));
}
for(int i = 1; i <= n; i++)
fa[i] = i;
dfs(1, 0);
for(int i = 1; i <= q; i++)
printf("%d\n", ans[i]);
return 0;
}
L
#include <cstdio>
#include <vector>
using namespace std;
const int N = 101, M = 1001, W = 11, p = 10000;
int n, m, u, v, w;
struct edge{
int u, v, w;
edge(int _u, int _v, int _w) : u(_u), v(_v), w(_w){}
};
vector<edge> e[W], mst;
int fa[N], a[N][N], id[N], cnt;
int find(int x){
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int det(int a[][N], int n, int p){
int ans = 1, k;
for (int i = 1; i <= n; i++){
for(k = i; k <= n; k++)
if(a[k][i])
break;
if(k > n)
return 0;
if(i != k){
swap(a[i], a[k]);
ans = -ans;
}
for (int j = i + 1; j <= n; j++){
if(a[j][i] > a[i][i]){
swap(a[j], a[i]);
ans = -ans;
}
while(a[j][i]){
int l = a[i][i] / a[j][i];
for (int k = i; k <= n; k++)
a[i][k] = (a[i][k] + 1ll * (p - l) * a[j][k]) % p;
swap(a[j], a[i]);
ans = -ans;
}
}
ans = 1ll * ans * a[i][i] % p;
}
return (ans + p) % p;
}
int main(){
scanf("%d%d", &n, &m);
while(m--){
scanf("%d%d%d", &u, &v, &w);
e[w].push_back(edge(u, v, w));
}
for (int i = 1; i <= n; i++)
fa[i] = i;
int sum = 0;
for (int i = 1; i < W; i++){
for(edge ed : e[i]){
int u = find(ed.u);
int v = find(ed.v);
if(u != v){
sum++;
fa[v] = u;
mst.push_back(ed);
}
}
}
if(sum != n - 1){
putchar('0');
return 0;
}
int ans = 1;
for (int i = 1; i < W; i++){
for (int j = 1; j <= n; j++)
fa[j] = j;
for (edge ed : mst)
if(ed.w != i){
int u = find(ed.u);
int v = find(ed.v);
if(u != v)
fa[v] = u;
}
cnt = 0;
for (int j = 1; j <= n; j++)
if(fa[j] == j)
id[j] = ++cnt;
if(cnt == 1)
continue;
for (int j = 1; j <= cnt; j++)
for (int k = 1; k <= cnt; k++)
a[j][k] = 0;
for(edge ed : e[i]){
int u = find(ed.u);
int v = find(ed.v);
if(u != v){
u = id[u];
v = id[v];
a[u][v]--;
a[v][u]--;
a[u][u]++;
a[v][v]++;
}
}
for (int j = 1; j <= cnt; j++)
for (int k = 1; k <= cnt; k++)
a[j][k] = (a[j][k] % p + p) % p;
ans = ans * det(a, cnt - 1, p) % p;
}
printf("%d", ans);
return 0;
}
M
#include <cstdio>
#include <vector>
#include <queue>
#include <functional>
#include <cstring>
using namespace std;
const int N = 4e5 + 1;
template<class type>
struct leftist{
struct node{
type val = type();
int ls = 0, rs = 0, d = 0;
node(){}
node(const type &_val) : val(_val){}
};
vector<node> data = vector<node>(1);
int create(const type &val){
data.push_back(node(val));
return data.size() - 1;
}
int duplicate(node &nd){
data.push_back(nd);
return data.size() - 1;
}
int merge(int x, int y){
if(!x || !y) return x | y;
if(data[x].val > data[y].val) swap(x, y);
x = duplicate(data[x]);
int res = merge(data[x].rs, y);
data[x].rs = res;
if(data[data[x].ls].d < data[data[x].rs].d)
swap(data[x].ls, data[x].rs);
data[x].d = data[data[x].rs].d + 1;
return x;
}
};
struct edge{
int u, v;
long long w;
edge(){}
edge(int _u, int _v, long long _w) : u(_u), v(_v), w(_w){}
bool operator>(const edge &b) const{
return w > b.w;
}
};
leftist<edge> heap;
int n, m, u, v, head[N], nxt[N], to[N], eid = 1;
long long k, w, val[N];
vector<edge> g[N];
void addedge(int u, int v, long long w){
to[eid] = v;
val[eid] = w;
nxt[eid] = head[u];
head[u] = eid++;
}
struct node{
int id = 0;
long long dist = 0;
node(int _id, long long _dist) : id(_id), dist(_dist){}
bool operator>(const node &b) const{
return dist > b.dist;
}
};
priority_queue<node, vector<node>, greater<node>> pq;
int fa[N], id[N];
long long dist[N];
void dfs(int u){
bool del = false;
for(edge e : g[u]){
if(!del && e.v == fa[u] && dist[e.v] + e.w == dist[u]){
del = true;
continue;
}
e.w = dist[e.v] - dist[u] + e.w;
if(!id[u]) id[u] = heap.create(e);
else id[u] = heap.merge(id[u], heap.create(e));
}
if(id[fa[u]]) id[u] = id[u] ? heap.merge(id[fa[u]], id[u]) : id[fa[u]];
for(int e = head[u]; e; e = nxt[e])
if(!id[to[e]] && fa[to[e]] == u) dfs(to[e]);
}
priority_queue<edge, vector<edge>, greater<edge>> kth;
int main(){
scanf("%d%d%lld", &n, &m, &k);
for(int i = 1; i <= m; i++){
scanf("%d%d%lld", &u, &v, &w);
// if(u == n) continue;
addedge(v, u, w);
g[u].push_back(edge(u, v, w));
}
memset(dist + 1, 0x3f, sizeof(long long) * n);
dist[n] = 0;
pq.push(node(n, 0));
while(!pq.empty()){
node nd = pq.top();
pq.pop();
int u = nd.id;
if(dist[u] < nd.dist) continue;
for(int e = head[u]; e; e = nxt[e])
if(dist[u] + val[e] < dist[to[e]]){
dist[to[e]] = dist[u] + val[e];
fa[to[e]] = u;
pq.push(node(to[e], dist[to[e]]));
}
}
dfs(n);
kth.push(edge(0, 1, dist[1]));
int cnt = 1;
while(kth.size() && cnt < k){
edge e = kth.top();
kth.pop();
cnt++;
if(id[e.v]) kth.push(edge(id[e.v], heap.data[id[e.v]].val.v, e.w + heap.data[id[e.v]].val.w));
if(heap.data[e.u].ls) kth.push(edge(heap.data[e.u].ls, heap.data[heap.data[e.u].ls].val.v,
e.w - heap.data[e.u].val.w + heap.data[heap.data[e.u].ls].val.w));
if(heap.data[e.u].rs) kth.push(edge(heap.data[e.u].rs, heap.data[heap.data[e.u].rs].val.v,
e.w - heap.data[e.u].val.w + heap.data[heap.data[e.u].rs].val.w));
}
printf("%lld\n", kth.size() && kth.top().w != 0x3f3f3f3f3f3f3f3f ? kth.top().w : -1);
return 0;
}
N
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 1001;
const long long INF = 0x3f3f3f3f3f3f3f3f;
int n, m, u, v, w, edge[N][N], order[N][N];
long long dist[N][N];
int main(){
memset(edge, 0x3f, sizeof(edge));
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
edge[i][i] = 0;
while(m--){
scanf("%d%d%d", &u, &v, &w);
edge[u][v] = edge[v][u] = min(edge[u][v], w);
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dist[i][j] = edge[i][j] == 0x3f3f3f3f ? INF : edge[i][j];
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++)
order[i][j] = j;
sort(order[i] + 1, order[i] + 1 + n, [&](int a, int b)
{ return dist[i][a] < dist[i][b]; });
}
long long ans = INF;
for (int i = 1; i <= n; i++)
ans = min(ans, dist[i][order[i][n]] * 2);
for (int u = 1; u < n; u++)
for (int v = u + 1; v <= n; v++)
if(edge[u][v] != 0x3f3f3f3f)
for (int p = n, j = n - 1; j >= 1; j--)
if (dist[v][order[u][j]] > dist[v][order[u][p]]){
ans = min(ans, dist[u][order[u][j]] + dist[v][order[u][p]] + edge[u][v]);
p = j;
}
printf("%lld", ans);
return 0;
}
O
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1e5 + 1, M = 2e5 + 1;
int n, m, s, u, v, w, head[N], nxt[M], to[M], val[M], eid = 1;
void addedge(int u, int v, int w){
to[eid] = v;
val[eid] = w;
nxt[eid] = head[u];
head[u] = eid++;
}
long long dist[N];
struct node{
long long dist;
int i;
node(long long _dist, int _i) : dist(_dist), i(_i){}
bool operator<(const node &b) const{
return dist > b.dist;
}
};
priority_queue<node> q;
int main(){
memset(dist, -1, sizeof(dist));
scanf("%d%d%d", &n, &m, &s);
while(m--){
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
}
dist[s] = 0;
q.push(node(0, s));
while(!q.empty()){
if(q.top().dist > dist[q.top().i]){
q.pop();
continue;
}
int i = q.top().i;
q.pop();
for(int e = head[i]; e; e = nxt[e]){
if(dist[to[e]] == -1 || dist[i] + val[e] < dist[to[e]]){
dist[to[e]] = dist[i] + val[e];
q.push(node(dist[to[e]], to[e]));
}
}
}
for (int i = 1; i <= n; i++)
printf("%lld\n", dist[i]);
return 0;
}
P
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int N = 405, M = 2 * N * (N + 1), X[4] = {-1, 0, 1, 0}, Y[4] = {0, 1, 0, -1};
int n, m, unit, a[N][N], ver[N][N], hor[N][N];
long long dist[N][N];
int from[N][N];
struct node{
long long dist;
int x, y;
node(long long _dist, int _x, int _y) : dist(_dist), x(_x), y(_y){}
bool operator<(const node &b) const{
return dist > b.dist;
}
};
priority_queue<node> pq;
bool legal(int x, int y){
return x >= 0 && y >= 0 && x <= n && y <= m;
}
bool del[N][N][4];
int head[4 * N * N], nxt[M * 4 + 8 * N * N], to[M * 4 + 8 * N * N], val[M * 4 + 8 * N * N], eid = 1;
void addedge(int u, int v, int w){
to[eid] = v;
val[eid] = w;
nxt[eid] = head[u];
head[u] = eid++;
}
void addundir(int u, int v, int w){
addedge(u, v, w);
addedge(v, u, w);
}
struct duo{
long long d;
int i;
duo(long long _d, int _i) : d(_d), i(_i){}
bool operator<(const duo &b) const{
return d > b.d;
}
};
priority_queue<duo> q;
long long d[4 * N * N];
long long dijkstra(int s, int t){
memset(d, 0x3f, sizeof(d));
d[s] = 0;
q.push(duo(0, s));
while(!q.empty()){
int i = q.top().i;
q.pop();
for (int e = head[i]; e; e = nxt[e])
if(d[to[e]] > d[i] + val[e]){
d[to[e]] = d[i] + val[e];
q.push(duo(d[to[e]], to[e]));
}
}
return d[t];
}
int main(){
scanf("%d%d", &n, &m);
unit = (n + 1) * (m + 1);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++){
scanf("%d", &a[i][j]);
if(a[i][j]){
del[i][j][1] = true;
del[i][j][2] = true;
del[i + 1][j][0] = true;
del[i + 1][j][1] = true;
del[i][j + 1][2] = true;
del[i][j + 1][3] = true;
del[i + 1][j + 1][3] = true;
del[i + 1][j + 1][0] = true;
}
}
for (int i = 0; i < n; i++)
for (int j = 0; j <= m; j++){
scanf("%d", &ver[i][j]);
addundir(i * (m + 1) + j + 1 + 2 * unit, (i + 1) * (m + 1) + j + 1 + 1 * unit, ver[i][j]);
addundir(i * (m + 1) + j + 1 + 3 * unit, (i + 1) * (m + 1) + j + 1 + 0 * unit, ver[i][j]);
}
for (int i = 0; i <= n; i++)
for (int j = 0; j < m; j++){
scanf("%d", &hor[i][j]);
addundir(i * (m + 1) + j + 1 + 1 * unit, i * (m + 1) + j + 2 + 0 * unit, hor[i][j]);
addundir(i * (m + 1) + j + 1 + 2 * unit, i * (m + 1) + j + 2 + 3 * unit, hor[i][j]);
}
memset(dist, 0x3f, sizeof(dist));
dist[0][0] = 0;
from[0][0] = -1;
pq.push(node(0, 0, 0));
while(!pq.empty()){
int x = pq.top().x;
int y = pq.top().y;
pq.pop();
if(x > 0 && dist[x - 1][y] > dist[x][y] + ver[x - 1][y]){
dist[x - 1][y] = dist[x][y] + ver[x - 1][y];
from[x - 1][y] = 0;
pq.push(node(dist[x - 1][y], x - 1, y));
}
if(y < m && dist[x][y + 1] > dist[x][y] + hor[x][y]){
dist[x][y + 1] = dist[x][y] + hor[x][y];
from[x][y + 1] = 1;
pq.push(node(dist[x][y + 1], x, y + 1));
}
if(x < n && dist[x + 1][y] > dist[x][y] + ver[x][y]){
dist[x + 1][y] = dist[x][y] + ver[x][y];
from[x + 1][y] = 2;
pq.push(node(dist[x + 1][y], x + 1, y));
}
if(y > 0 && dist[x][y - 1] > dist[x][y] + hor[x][y - 1]){
dist[x][y - 1] = dist[x][y] + hor[x][y - 1];
from[x][y - 1] = 3;
pq.push(node(dist[x][y - 1], x, y - 1));
}
}
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if(a[i][j]){
int x = i, y = j;
while(from[x][y] != -1){
int t = from[x][y];
from[x][y] = -1;
del[x][y][(t + 2) % 4] = 1;
x -= X[t], y -= Y[t];
del[x][y][t] = 1;
}
}
del[0][0][0] = 1;
del[0][0][3] = 1;
for (int i = 0; i <= n; i++)
for (int j = 0; j <= m; j++)
for (int t = 0; t < 4; t++)
if(!del[i][j][t])
addundir(i * (m + 1) + j + 1 + t * unit, i * (m + 1) + j + 1 + (t + 1) % 4 * unit, 0);
printf("%lld", dijkstra(1 + unit, 1 + 3 * unit));
return 0;
}
Q
#include <cstdio>
#include <iostream>
#define le (i << 1)
#define ri (i << 1 | 1)
using namespace std;
const int N = 1e5 + 1;
const long long INF = 0x3f3f3f3f3f3f3f3f;
int n, d, a[N], pos[2][N << 2];
bool same[2][N << 2];
long long ans[2][N << 2], num[2][N << 2], val[2][N << 2];
void pushup(int id, int i){
num[id][i] = max(num[id][le], num[id][ri]);
if(same[id][le] && same[id][ri] && num[id][le] == num[id][ri])
same[id][i] = true;
val[id][i] = min(val[id][le], val[id][ri]);
if(ans[id][le] < ans[id][ri]){
ans[id][i] = ans[id][le];
pos[id][i] = pos[id][le];
}else{
ans[id][i] = ans[id][ri];
pos[id][i] = pos[id][ri];
}
}
void pushdown(int id, int i){
if(same[id][i]){
same[id][le] = same[id][ri] = true;
num[id][le] = num[id][ri] = num[id][i];
ans[id][le] = val[id][le] + num[id][le];
ans[id][ri] = val[id][ri] + num[id][ri];
same[id][i] = false;
}
}
void build(int i, int l, int r){
num[0][i] = INF;
num[1][i] = INF;
same[0][i] = true;
same[1][i] = true;
if(l == r){
val[0][i] = a[l] + 1ll * l * d;
val[1][i] = a[l] - 1ll * l * d;
ans[0][i] = val[0][i] + num[0][i];
ans[1][i] = val[1][i] + num[1][i];
pos[0][i] = l;
pos[1][i] = l;
return;
}
int mid = (l + r) >> 1;
build(le, l, mid);
build(ri, mid + 1, r);
pushup(0, i);
pushup(1, i);
}
int L, R;
long long K;
void tomin(int id, int i, int l, int r){
if(num[id][i] <= K)
return;
if(l >= L && r <= R && same[id][i] && num[id][i] > K){
same[id][i] = true;
num[id][i] = K;
ans[id][i] = val[id][i] + num[id][i];
return;
}
pushdown(id, i);
int mid = (l + r) >> 1;
if(mid >= L)
tomin(id, le, l, mid);
if(mid < R)
tomin(id, ri, mid + 1, r);
pushup(id, i);
}
int P;
void del(int id, int i, int l, int r){
if(l == r){
val[id][i] = INF;
ans[id][i] = val[id][i] + num[id][i];
return;
}
pushdown(id, i);
int mid = (l + r) >> 1;
if(mid >= P)
del(id, le, l, mid);
else
del(id, ri, mid + 1, r);
pushup(id, i);
}
int main(){
scanf("%d%d", &n, &d);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, 1, n);
same[0][1] = same[1][1] = true;
ans[0][1] = ans[1][1] = INF;
int p = 1;
long long sum = 0;
for (int i = 1; i < n; i++){
P = p;
del(0, 1, 1, n);
del(1, 1, 1, n);
L = p + 1, R = n, K = -1ll * p * d + a[p];
if(L <= R)
tomin(0, 1, 1, n);
L = 1, R = p - 1, K = 1ll * p * d + a[p];
if(L <= R)
tomin(1, 1, 1, n);
if(ans[0][1] < ans[1][1]){
p = pos[0][1];
sum += ans[0][1];
}else{
p = pos[1][1];
sum += ans[1][1];
}
}
printf("%lld", sum);
return 0;
}
R
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 101, M = 10001, INF = 0x7fffffff;
int n, m, s, u[M], v[M], w[M], id[N], pre[N], minw[N], src, idx;
int vis[N];
int zhuliu(){
w[0] = INF;
int ret = 0;
while(true){
memset(pre, 0, sizeof(pre));
for (int i = 1; i <= m; i++)
if(u[i] != v[i] && (!pre[v[i]] || minw[v[i]] > w[i])){
pre[v[i]] = u[i];
minw[v[i]] = w[i];
}
for (int i = 1; i <= n; i++)
if(i != s && !pre[i])
return -1;
idx = 0;
memset(id, 0, sizeof(id));
memset(vis, 0, sizeof(vis));
vis[s] = -1;
for (int i = 1; i <= n; i++)
if(i != s){
ret += minw[i];
int j = i;
while(!vis[j]){
vis[j] = i;
j = pre[j];
}
if(j != s && vis[j] == i){
id[j] = ++idx;
for (int k = pre[j]; k != j; k = pre[k])
id[k] = idx;
}
}
if(idx == 0)
break;
for (int i = 1; i <= n; i++)
if(!id[i])
id[i] = ++idx;
for (int i = 1; i <= m; i++){
if (id[u[i]] != id[v[i]])
w[i] -= minw[v[i]];
u[i] = id[u[i]], v[i] = id[v[i]];
}
s = id[s];
n = idx;
}
return ret;
}
int main(){
scanf("%d%d%d", &n, &m, &s);
for (int i = 1; i <= m; i++)
scanf("%d%d%d", &u[i], &v[i], &w[i]);
printf("%d", zhuliu());
return 0;
}
S
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
const int N = 1001, M = 2e5 + 1;
int n, m, u, v, match[N], col[N], pre[N], raw[N], fa[N], head[N], nxt[M << 1], to[M << 1], eid = 1;
void addedge(int u, int v){
to[eid] = v;
nxt[eid] = head[u];
head[u] = eid++;
}
int find(int x){
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int tag[N], idx;
int lca(int u, int v){
u = find(u);
v = find(v);
idx++;
do{
tag[u] = idx;
u = find(pre[match[u]]);
if(v) swap(u, v);
}while(tag[u] != idx);
return u;
}
queue<int> q;
void blossom(int u, int v, int m){
while(find(u) != m){
pre[u] = v;
v = match[u];
if(col[v] == 0){
col[v] = 1;
q.push(v);
}
fa[u] = m;
fa[v] = m;
u = pre[v];
}
}
int solve(int u){
q = queue<int>();
memcpy(fa + 1, raw + 1, sizeof(int) * n);
memset(col + 1, -1, sizeof(int) * n);
pre[u] = 0;
col[u] = 1;
q.push(u);
while(!q.empty()){
int u = q.front();
q.pop();
for(int e = head[u]; e; e = nxt[e]){
int v = to[e];
if(find(u) == find(v) || col[v] == 0) continue;
if(col[v] == -1){
pre[v] = u;
col[v] = 0;
if(!match[v]){
for(int _v = match[pre[v]]; v; v = _v, _v = match[pre[v]]){
match[v] = pre[v];
match[pre[v]] = v;
}
return 1;
}
col[match[v]] = 1;
q.push(match[v]);
}else{
int m = lca(u, v);
blossom(u, v, m);
blossom(v, u, m);
}
}
}
return 0;
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
raw[i] = i;
while(m--){
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
int ans = 0;
for(int i = 1; i <= n; i++)
if(!match[i]) ans += solve(i);
printf("%d\n", ans);
return 0;
}
T
#include <cstring>
#include <iostream>
using namespace std;
const int MAX_N = 1005;
const int MAX_M = 1000005;
struct Edge {
int v, next;
} e[MAX_M];
int p[MAX_N], eid;
void init() {
memset(p, -1, sizeof(p));
eid = 0;
}
void insert(int u, int v) {
e[eid].v = v;
e[eid].next = p[u];
p[u] = eid++;
}
bool vis[MAX_N];
int rmatch[MAX_N];
bool dfs(int u) {
for (int i = p[u]; i != -1; i = e[i].next) {
int v = e[i].v;
if (!vis[v]) {
vis[v] = true;
if (rmatch[v] == -1 || dfs(rmatch[v])) {
rmatch[v] = u;
return true;
}
}
}
return false;
}
int hungary(int n) {
int res = 0;
memset(rmatch, -1, sizeof(rmatch));
for (int i = 1; i <= n; ++i) {
memset(vis, 0, sizeof(vis));
res += dfs(i);
}
return res;
}
int path[MAX_N];
int main() {
int n, m;
scanf("%d%d", &n, &m);
init();
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d%d", &u, &v);
insert(u, v);
}
printf("%d", n - hungary(n));
return 0;
}

浙公网安备 33010602011771号