-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
786 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
\section{技巧总结} | ||
\subsection{最大流} | ||
\begin{itemize} | ||
\item 若一个点只能被经过有限次,将其拆为入点和出点,入点到出点连流量为 | ||
经过次数限制的边。 | ||
\item 树形最大流可以贪心解决。 | ||
\end{itemize} | ||
\subsection{最小割} | ||
\begin{itemize} | ||
\item 最大化收益可以理解为已经拿到所有收益,最小化损失。然后将其转化为最小割解决。 | ||
\item 使用$+\infty$边描述依赖关系,可以保证这条边不出现在最小割中。 | ||
\item 用$S,T$与点的连边来表示点的权。 | ||
\end{itemize} | ||
\subsection{费用流} | ||
\begin{itemize} | ||
\item 要求费用最小且边数最小:类比进制的思想,实际费用乘以一个大于总边数的因子,再加上 | ||
1作为该边边权。 | ||
\item 若已知走一条边之前必定已经走完了另外几条边,则考虑动态加边。 | ||
\item 对于层数较少,结构简单的图,考虑使用其它数据结构贪心模拟费用流。 | ||
\item (待验证)判断一条边是否一定被选:在残量网络上跑SPFA,若距离差不等于边权则必选。 | ||
\item 餐巾计划问题: | ||
\end{itemize} | ||
|
||
上述内容参考了胡伯涛的2007年国家集训队论文《最小割模型在信息学竞赛中的应用》 | ||
\cite{MCIOI}和租酥雨的博客\footnote{ | ||
网络流总结\\ | ||
\url{https://www.cnblogs.com/zhoushuyu/p/8137534.html} | ||
}。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
#include <algorithm> | ||
#include <cstdio> | ||
int read() { | ||
int res = 0, c; | ||
do | ||
c = getchar(); | ||
while(c < '0' || c > '9'); | ||
while('0' <= c && c <= '9') { | ||
res = res * 10 + c - '0'; | ||
c = getchar(); | ||
} | ||
return res; | ||
} | ||
const int size = 70000; | ||
template <int esiz> | ||
struct G { | ||
struct Edge { | ||
int to, nxt; | ||
} E[esiz]; | ||
int last[size], cnt; | ||
G() : cnt(0) {} | ||
void addEdge(int u, int v) { | ||
++cnt; | ||
E[cnt].to = v, E[cnt].nxt = last[u]; | ||
last[u] = cnt; | ||
} | ||
}; | ||
G<size * 2> A; | ||
G<size> B; | ||
int in[size], q[size], d[size], p[size][16], siz[size]; | ||
void DFS(int u) { | ||
siz[u] = 1; | ||
for(int i = B.last[u]; i; i = B.E[i].nxt) { | ||
int v = B.E[i].to; | ||
if(v != p[u][0]) { | ||
DFS(v); | ||
siz[u] += siz[v]; | ||
} | ||
} | ||
} | ||
int getLCA(int u, int v) { | ||
if(u == 0 || v == 0) | ||
return u | v; | ||
if(d[u] < d[v]) | ||
std::swap(u, v); | ||
int delta = d[u] - d[v]; | ||
for(int i = 0; i < 16; ++i) | ||
if(delta & (1 << i)) | ||
u = p[u][i]; | ||
if(u == v) | ||
return u; | ||
for(int i = 15; i >= 0; --i) | ||
if(p[u][i] != p[v][i]) | ||
u = p[u][i], v = p[v][i]; | ||
return p[u][0]; | ||
} | ||
int main() { | ||
int n = read(); | ||
for(int i = 1; i <= n; ++i) { | ||
int k = read(); | ||
while(k) { | ||
++in[i]; | ||
A.addEdge(k, i); | ||
k = read(); | ||
} | ||
} | ||
int qcnt = 0, rt = n + 1; | ||
for(int i = 1; i <= n; ++i) | ||
if(!in[i]) { | ||
B.addEdge(rt, i); | ||
p[i][0] = rt; | ||
q[++qcnt] = i; | ||
d[i] = 1; | ||
} | ||
for(int i = 1; i <= qcnt; ++i) { | ||
int u = q[i]; | ||
for(int j = A.last[u]; j; j = A.E[j].nxt) { | ||
int v = A.E[j].to; | ||
p[v][0] = getLCA(p[v][0], u); | ||
if(--in[v] == 0) { | ||
B.addEdge(p[v][0], v); | ||
d[v] = d[p[v][0]] + 1; | ||
for(int k = 1; k < 16; ++k) | ||
p[v][k] = p[p[v][k - 1]][k - 1]; | ||
q[++qcnt] = v; | ||
} | ||
} | ||
} | ||
DFS(rt); | ||
for(int i = 1; i <= n; ++i) | ||
printf("%d\n", siz[i] - 1); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
#include <algorithm> | ||
#include <cassert> | ||
#include <cmath> | ||
#include <csetjmp> | ||
#include <cstdio> | ||
#include <cstring> | ||
namespace IO { | ||
void init() { | ||
assert(setvbuf(stdin, 0, _IONBF, 0) == 0); | ||
assert(setvbuf(stdout, 0, _IONBF, 0) == 0); | ||
} | ||
const int size = 1 << 21; | ||
char in[size]; | ||
char getc() { | ||
static char *S = in, *T = in; | ||
if(S == T) | ||
S = in, T = in + fread(in, 1, size, stdin); | ||
return S == T ? EOF : *S++; | ||
} | ||
} | ||
int read() { | ||
int res = 0, c; | ||
bool flag = false; | ||
do { | ||
c = IO::getc(); | ||
flag |= c == '-'; | ||
} while(c < '0' || c > '9'); | ||
while('0' <= c && c <= '9') { | ||
res = res * 10 + c - '0'; | ||
c = IO::getc(); | ||
} | ||
return flag ? -res : res; | ||
} | ||
const int size = 105, maxk = 1005, inf = 0x3f3f3f3f; | ||
typedef double FT; | ||
const FT eps = 1e-2; | ||
struct Edge { | ||
int to, nxt; | ||
FT w; | ||
} E[size * size]; | ||
int last[size], cnt; | ||
void addEdge(int u, int v, FT w) { | ||
++cnt; | ||
E[cnt].to = v, E[cnt].nxt = last[u], E[cnt].w = w; | ||
last[u] = cnt; | ||
} | ||
FT dis[size]; | ||
bool vis[size]; | ||
jmp_buf buf; | ||
bool pre(int u) { | ||
FT cd = dis[u]; | ||
vis[u] = true; | ||
bool res = false; | ||
for(int i = last[u]; i; i = E[i].nxt) { | ||
int v = E[i].to; | ||
FT dv = cd + E[i].w; | ||
if(dv < dis[v]) { | ||
if(vis[v]) | ||
longjmp(buf, 1); | ||
dis[v] = dv; | ||
pre(v); | ||
res = true; | ||
break; | ||
} | ||
} | ||
vis[u] = false; | ||
return res; | ||
} | ||
void DFS(int u, int d) { | ||
if(d == 0) | ||
return; | ||
FT cd = dis[u]; | ||
vis[u] = true; | ||
for(int i = last[u]; i; i = E[i].nxt) { | ||
int v = E[i].to; | ||
FT dv = cd + E[i].w; | ||
if(dv < dis[v]) { | ||
if(vis[v]) | ||
longjmp(buf, 1); | ||
dis[v] = dv; | ||
DFS(v, d - 1); | ||
} | ||
} | ||
vis[u] = false; | ||
} | ||
int link[size][size], off[size][size]; | ||
bool check(int n, int K, FT x) { | ||
cnt = 0; | ||
memset(last + 1, 0, sizeof(int) * n); | ||
for(int i = 1; i <= n; ++i) | ||
for(int j = 1; j <= n; ++j) { | ||
if(off[i][j] != inf && link[i][j] != inf) | ||
addEdge(i, j, | ||
off[i][j] + link[i][j] * x); | ||
} | ||
memset(vis + 1, 0, sizeof(bool) * n); | ||
memset(dis + 1, 0, sizeof(double) * n); | ||
if(setjmp(buf)) | ||
return true; | ||
else { | ||
for(int i = 1; i <= n; ++i) | ||
while(pre(i)) | ||
; | ||
int end = 2 * n; | ||
for(int k = 1; k < end; k <<= 1) | ||
for(int i = 1; i <= n; ++i) | ||
DFS(i, k); | ||
return false; | ||
} | ||
} | ||
int b[size][maxk], s[size][maxk]; | ||
int main() { | ||
IO::init(); | ||
int n = read(); | ||
int m = read(); | ||
int K = read(); | ||
for(int i = 1; i <= n; ++i) | ||
for(int j = 1; j <= K; ++j) { | ||
b[i][j] = read(); | ||
s[i][j] = read(); | ||
} | ||
for(int i = 1; i <= n; ++i) | ||
for(int j = 1; j <= n; ++j) { | ||
int& mind = off[i][j]; | ||
mind = inf; | ||
if(i == j) | ||
continue; | ||
for(int k = 1; k <= K; ++k) | ||
if(b[i][k] != -1 && s[j][k] != -1) | ||
mind = std::min(mind, | ||
b[i][k] - s[j][k]); | ||
} | ||
memset(link, 0x3f, sizeof(link)); | ||
for(int i = 1; i <= m; ++i) { | ||
int u = read(); | ||
int v = read(); | ||
int t = read(); | ||
link[u][v] = std::min(link[u][v], t); | ||
} | ||
for(int k = 1; k <= n; ++k) | ||
for(int i = 1; i <= n; ++i) | ||
if(link[i][k] != inf) | ||
for(int j = 1; j <= n; ++j) | ||
link[i][j] = std::min( | ||
link[i][j], | ||
link[i][k] + link[k][j]); | ||
FT l = 100.0, r = 350.0; | ||
while(floor(r + eps) - floor(l + eps) >= eps) { | ||
FT m = (l + r) / 2.0; | ||
(check(n, K, m) ? l : r) = m; | ||
} | ||
printf("%.0lf\n", floor(r + eps)); | ||
return 0; | ||
} |
Oops, something went wrong.