mirror of
https://github.com/Kiritow/OJ-Problems-Source.git
synced 2024-03-22 13:11:29 +08:00
226 lines
7.3 KiB
C++
226 lines
7.3 KiB
C++
//邻接表
|
||
typedef int wtype;
|
||
const wtype INF = 0x3f3f3f3f;
|
||
int head[N], to[M], nxt[M], tot; wtype len[M];
|
||
void init() { tot = 0; memset(head, -1, sizeof(head)); }
|
||
void addedge(int x, int y, wtype z) { to[tot] = y; len[tot] = z; nxt[tot] = head[x]; head[x] = tot++; }
|
||
//Dijkstra + priority_queue + 邻接矩阵 O(V^2)
|
||
typedef int wtype;
|
||
struct Node {
|
||
int v; wtype w;
|
||
bool operator<(const Node &r)const { return w > r.w; }
|
||
};
|
||
int n, pre[N]; wtype mp[N][N], dist[N]; bool vis[N]; //邻接矩阵初始化为INF
|
||
void Dijkstra(int src) {
|
||
memset(dist, 0x3f, sizeof(dist));
|
||
memset(vis, 0, sizeof(vis)); memset(pre, -1, sizeof(pre));
|
||
priority_queue<Node> que; que.push((Node) {src, dist[src] = 0});
|
||
while (!que.empty()) {
|
||
int u = que.top().v; que.pop();
|
||
if (vis[u]) { continue; }
|
||
vis[u] = true;
|
||
for (int v = 0; v < n; v++) {
|
||
if (!vis[v] && dist[v] > dist[u] + mp[u][v]) {
|
||
dist[v] = dist[u] + mp[u][v]; pre[v] = u; que.push((Node) {v, dist[v]});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//Dijkstra + priority_queue + vector存边 O((V+E)logV)
|
||
typedef int wtype;
|
||
struct Node {
|
||
int v; wtype w;
|
||
bool operator<(const Node &r)const { return w > r.w; }
|
||
};
|
||
vector<Node> e[N]; wtype dist[N]; bool vis[N];
|
||
void Dijkstra(int src) {
|
||
memset(dist, 0x3f, sizeof(dist));
|
||
memset(vis, 0, sizeof(vis));
|
||
priority_queue<Node> que; que.push((Node) {src, dist[src] = 0});
|
||
while (!que.empty()) {
|
||
int u = que.top().v; que.pop();
|
||
if (vis[u]) { continue; }
|
||
vis[u] = true;
|
||
for (int i = 0; i < (int)e[u].size(); i++) {
|
||
int v = e[u][i].v; wtype w = e[u][i].w;
|
||
if (!vis[v] && dist[v] > dist[u] + w) {
|
||
dist[v] = dist[u] + w; que.push((Node) {v, dist[v]});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//Dijkstra + priority_queue + 邻接表 O((V+E)logV)
|
||
typedef int wtype;
|
||
struct Node {
|
||
int v; wtype w;
|
||
bool operator<(const Node &r)const { return w > r.w; }
|
||
};
|
||
wtype dist[N];
|
||
void Dijkstra(int src) {
|
||
memset(dist, 0x3f, sizeof(dist));
|
||
priority_queue<Node> que; que.push((Node) {src, dist[src] = 0});
|
||
while (!que.empty()) {
|
||
int u = que.top().v; wtype w = que.top().w; que.pop();
|
||
if (w > dist[u]) { continue; }
|
||
for (int i = head[u]; ~i; i = nxt[i]) {
|
||
int v = to[i];
|
||
if (dist[v] > len[i] + w) {
|
||
dist[v] = w + len[i]; que.push((Node) {v, dist[v]});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//SPFA + queue/stack + vector存边 O(kE)
|
||
typedef int wtype;
|
||
struct Edge { int v; wtype w; };
|
||
vector<Edge> e[N]; int cnt[N], pre[N]; wtype dist[N]; bool vis[N];
|
||
bool SPFA(int src) {
|
||
memset(dist, 0x3f, sizeof(dist)); dist[src] = 0;
|
||
memset(cnt, 0, sizeof(cnt)); cnt[src] = 1;
|
||
memset(vis, 0, sizeof(vis)); vis[src] = true;
|
||
memset(pre, -1, sizeof(pre));
|
||
queue<int> que; que.push(src); //stack
|
||
while (!que.empty()) {
|
||
int u = que.front(); que.pop();
|
||
vis[u] = false;
|
||
for (int i = 0; i < (int)e[u].size(); i++) {
|
||
int v = e[u][i].v; wtype w = e[u][i].w;
|
||
if (dist[v] > dist[u] + w) {
|
||
dist[v] = dist[u] + w; pre[v] = u;
|
||
if (!vis[v]) {
|
||
vis[v] = true; que.push(v);
|
||
if (++cnt[v] > n) { return false; } //有负环回路
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return true; //没有负环回路
|
||
}
|
||
//SPFA + SLF + LLL + 邻接表 O(kE)
|
||
typedef int wtype;
|
||
wtype dist[N];
|
||
bool vis[M];
|
||
void SPFA(int src) {
|
||
memset(dist, 0x3f, sizeof(dist)); dist[src] = 0;
|
||
memset(vis, 0, sizeof(vis)); vis[src] = true;
|
||
deque<int> que; que.push_back(src);
|
||
ll sum = 0;
|
||
while (!que.empty()) {
|
||
int u = que.front(); que.pop_front();
|
||
if (!que.empty() && (ll)dist[u] * que.size() > sum) { que.push_back(u); continue; }
|
||
sum -= dist[u]; vis[u] = false;
|
||
for (int i = head[u]; ~i; i = nxt[i]) {
|
||
int v = to[i]; wtype d = dist[u] + len[i];
|
||
if (d < dist[v]) {
|
||
if (vis[v]) { sum += d - dist[v]; }
|
||
dist[v] = d;
|
||
if (!vis[v]) {
|
||
if (!que.empty() && dist[que.front()] > dist[v]) { que.push_front(v); }
|
||
else { que.push_back(v); }
|
||
sum += dist[v]; vis[v] = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//差分约束系统
|
||
//a向b连一条权值为c的有向边表示b − a <= c, 用SPFA判断是否存在负环, 存在即无解
|
||
//Bellman-Ford + vector O(VE)
|
||
//可以处理负边权图, 可以判断是否存在负环回路, 当且仅当图中不包含从源点可达的负权回路时返回true
|
||
typedef int wtype;
|
||
struct Edge { int u, v; wtype w; };
|
||
vector<Edge> e;
|
||
wtype dist[N];
|
||
bool BellmanFord(int src) {
|
||
memset(dist, 0x3f, sizeof(dist)); dist[src] = 0;
|
||
for (int i = 1; i < n; i++) {
|
||
bool flag = false;
|
||
for (int j = 0; j < (int)e.size(); j++) {
|
||
int u = e[j].u, v = e[j].v; wtype w = e[j].w;
|
||
if (dist[v] > dist[u] + w) { dist[v] = dist[u] + w; flag = true; }
|
||
}
|
||
if (!flag) { return true; } //没有负环回路
|
||
}
|
||
for (int j = 0; j < (int)e.size(); j++) {
|
||
int u = e[j].u, v = e[j].v; wtype w = e[j].w;
|
||
if (dist[v] > dist[u] + w) { return false; } //有负环回路
|
||
}
|
||
return true; //没有负环回路
|
||
}
|
||
//Floyd 带路径记录 O(V^3)
|
||
typedef int wtype;
|
||
int n, pre[N][N]; wtype mp[N][N]; //初始化为INF
|
||
void Floyd() {
|
||
for (int i = 1; i <= n; i++) {
|
||
for (int j = 1; j <= n; j++) { pre[i][j] = (i == j) ? -1 : i; }
|
||
}
|
||
for (int k = 1; k <= n; k++) {
|
||
for (int i = 1; i <= n; i++) {
|
||
for (int j = 1; j <= n; j++) {
|
||
if (mp[i][k] + mp[k][j] < mp[i][j]) {
|
||
mp[i][j] = mp[i][k] + mp[k][j]; pre[i][j] = pre[k][j];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//无负权图的最小环
|
||
//有向图: mp[i][i] = INF, 然后跑floyd, ans = min(d[i][i])
|
||
//求无向图中经过至少3个点的最小环:
|
||
typedef int wtype;
|
||
const wtype INF = 0x3f3f3f3f;
|
||
int n; wtype mp[N][N], d[N][N]; //初始化为INF
|
||
wtype cycFloyd() {
|
||
memcpy(d, mp, sizeof(mp)); wtype ret = INF;
|
||
for (int k = 1; k <= n; k++) {
|
||
for (int i = 1; i < k; i++) {
|
||
for (int j = i + 1; j < k; j++) {
|
||
ans = min(ans, d[i][j] + mp[i][k] + mp[k][j]);
|
||
}
|
||
}
|
||
for (int i = 1; i <= n; i++) {
|
||
for (int j = 1; j <= n; j++) {
|
||
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
//Astar求k短路
|
||
typedef int wtype;
|
||
const wtype INF = 0x3f3f3f3f;
|
||
int head[N], to[M], nxt[M], tot; wtype len[M];
|
||
int rhead[N], rto[M], rnxt[M], rtot; wtype rlen[M];
|
||
void init() { tot = rtot = 0; memset(head, -1, sizeof(head)); memset(rhead, -1, sizeof(rhead)); }
|
||
void addedge(int x, int y, wtype z) {
|
||
to[tot] = y; len[tot] = z; nxt[tot] = head[x]; head[x] = tot++;
|
||
rto[rtot] = x; rlen[rtot] = z; rnxt[rtot] = rhead[y]; rhead[y] = rtot++;
|
||
}
|
||
struct Node {
|
||
int v; wtype w;
|
||
bool operator<(const Node &r)const { return w > r.w; }
|
||
};
|
||
int vis[N]; wtype dist[N], ans[N]; //前k短路
|
||
void Astar(int src, int des, int k) {
|
||
memset(dist, 0x3f, sizeof(dist)); memset(ans, 0x3f, sizeof(ans)); memset(vis, 0, sizeof(vis));
|
||
priority_queue<Node> que; que.push((Node) {des, dist[des] = 0});
|
||
while (!que.empty()) {
|
||
int u = que.top().v; wtype w = que.top().w; que.pop();
|
||
if (w > dist[u]) { continue; }
|
||
for (int i = rhead[u]; ~i; i = rnxt[i]) {
|
||
int v = rto[i];
|
||
if (dist[v] > rlen[i] + w) {
|
||
dist[v] = w + rlen[i]; que.push((Node) {v, dist[v]});
|
||
}
|
||
}
|
||
}
|
||
if (dist[src] < INF) { que.push((Node) {src, dis[src]}); }
|
||
while (!que.empty()) {
|
||
int u = que.top().v; wtype w = que.top().w; que.pop();
|
||
if (u == des && vis[des] <= k) { ans[vis[des]] = w; }
|
||
if (vis[u] > k) { continue; }
|
||
for (int i = head[u]; ~i; i = nxt[i]) {
|
||
int v = to[i]; que.push((Node) {v, w - dist[u] + dist[v] + len[i]});
|
||
}
|
||
}
|
||
}
|