数学有关的东西
gcd:
可以交在传送门洛谷2152拿完20分就跑23333(正解需要高精+一堆处理)
#include <cstdio>
#include <cstring>
#include <algorithm>
long long a, b;
long long gcd(long long a, long long b) {
if (b == 0) return (a);
return (gcd(b, a % b));
}
int main () {
scanf("%lld %lld", &a, &b);
printf("%lld", gcd(a, b));
return 0;
}
exgcd:
#include <cstdio>
#include <cstring>
#include <algorithm>
int a, b, x, y;
void exgcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return;
}
exgcd(b, a % b, x, y);
int t = x;
x = y;
y = t - a / b * y;
}
int main () {
scanf("%d %d", &a, &b);
exgcd(a, b, x, y);
x = ((x % b) + b ) % b;
printf("%d", x);
return 0;
}
快速幂:
#include <cstdio>
#include <cstring>
#include <algorithm>
long long b, p, k;
long long qpow(long long base, long long v, long long mod) {
long long ans = 1;
while (v > 0) {
if (v & 1) ans = (ans * base) % mod;
base = (base * base) % mod;
v = v >> 1;
}
return (ans);
}
int main () {
scanf("%lld %lld %lld", &b, &p, &k);
printf("%lld^%lld mod %lld=%lld", b, p, k, qpow(b, p, k));
return 0;
}
欧拉筛法:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 10000000 + 5000;
int n, m;
int prime[maxn], isp[maxn];
int ptot = 0;
int x;
int main () {
scanf("%d %d", &n, &m);
for (int i = 2; i <= n; i++) isp[i] = 1;
for (int i = 2; i <= n; i++) {
if (isp[i]) {
ptot++;
prime[ptot] = i;
}
long long k;
for (int j = 1; j <= ptot && (k = 1ll * prime[j] * i) <= n; j++) {
isp[k] = 0;
if (!(i % prime[j])) break;
}
}
for (int i = 1; i <= m; i++) {
scanf("%d", &x);
if (isp[x]) printf("Yes\n");
else printf("No\n");
}
return 0;
}
最长不上升子序列:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 300000 + 500;
int n;
int a[maxn];
int d[maxn];
int len = 0;
int x;
int ans;
int main () {
d[0] = 0x7fffffff;
n = 1;
while (scanf("%d", &a[n]) == 1) {
if (a[n] <= d[len]) {
len++;
d[len] = a[n];
} else {
int l = 0, r = len;
while (l <= r) {
int mid = (l + r) >> 1;
if (d[mid] >= a[n]) {
l = mid + 1;
ans = mid;
} else {
r = mid - 1;
}
}
d[ans+1] = a[n];
}
n++;
}
printf("%d\n", len);
memset(d, 0, sizeof(d));
// printf("%d", n);
n--;
len = 0;
for (int i = 1; i <= n; i++) {
if (a[i] > d[len]) {
len++;
d[len] = a[i];
} else {
int l = 0, r = len;
while (l <= r) {
int mid = (l + r) >> 1;
if (d[mid] < a[i]) {
l = mid + 1;
ans = mid;
} else {
r = mid - 1;
}
}
d[ans+1] = a[i];
}
}
printf("%d", len);
return 0;
}
高精度加法,读入,输出:
传送门洛谷1601
注意进位时要用+=
#include <cstdio>
#include <cstring>
#include <algorithm>
int tt[1000];
struct bigint {
int num;
int a[1000];
void print() {
for (int j = num; j >= 1; j--) {
printf("%d", a[j]);
}
printf("\n");
}
void readint() {
memset(tt, 0, sizeof(tt));
char c = getchar();
num = 0;
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') {
num++;
tt[num] = c - '0';
c = getchar();
}
for (int i = 1; i <= num; i++)
a[i] = tt[num - i + 1];
}
void clear0() {
num = 0;
memset(a, 0, sizeof(a));
}
void clear1() {
num = 1;
memset(a, 0, sizeof(a));
a[1] = 1;
}
};
bigint aa, bb;
bigint cc;
bigint operator + (bigint xx, bigint yy) {
bigint cc;
cc.clear0();
cc.num = std :: max(xx.num, yy.num);
for (int i = 1; i <= cc.num; i++) {
cc.a[i] += xx.a[i] + yy.a[i];
if (cc.a[i] >= 10) {
cc.a[i+1] += cc.a[i] / 10;
cc.a[i] = cc.a[i] % 10;
}
}
if (cc.a[cc.num + 1] == 0) return (cc);
cc.num++;
while (cc.a[cc.num] >= 10) {
cc.a[cc.num+1] += cc.a[cc.num] / 10;
cc.a[cc.num] = cc.a[cc.num] % 10;
}
return (cc);
}
int main () {
aa.readint();
bb.readint();
// aa.print();
// bb.print();
cc = aa + bb;
cc.print();
return 0;
}
矩阵快速幂:
传送门洛谷3390
手一抖就把乘号打成了加号
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 110;
const long long mod = 1e9 + 7;
int n;
struct data {
long long a[maxn][maxn];
void clear0(void) {
memset(a, 0, sizeof(a));
}
void clear1(void) {
memset(a, 0, sizeof(a));
for (int i = 1; i <= n; i++) a[i][i] = 1;
}
void print() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) printf("%d ", a[i][j]);
printf("\n");
}
}
};
long long k;
data aa;
data ans;
data operator * (data xx, data yy) {
data cc;
cc.clear0();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++) cc.a[i][j] = (cc.a[i][j] + xx.a[i][k] * yy.a[k][j]) % mod;
return (cc);
}
data qpow(data aa, long long v, long long mod) {
data ans;
ans.clear1();
while (v > 0) {
if (v & 1) ans = ans * aa;
v = v >> 1;
aa = aa * aa;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) ans.a[i][j] %= mod;
return ans;
}
int main () {
scanf("%d %lld", &n, &k);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
scanf("%d", &aa.a[i][j]);
aa.a[i][j] %= mod;
}
ans = qpow(aa, k, mod);
ans.print();
return 0;
}
数据结构:
树状数组:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 550000;
int c[maxn];
int n, m;
int x;
int odd, y;
inline int lowbit(int x) {
return (x & (-x));
}
void change(int x, int z) {
while (x <= n) {
c[x] += z;
x += lowbit(x);
}
}
long long xfind(int x) {
long long ans = 0;
while (x > 0) {
ans += c[x];
x -= lowbit(x);
}
return (ans);
}
int main () {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &x);
change(i, x);
}
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &odd, &x, &y);
if (odd == 1) {
change(x, y);
} else {
printf("%lld\n", xfind(y) - xfind(x-1));
}
}
return 0;
}
线段树:
传送门洛谷3372
手抖数组没开三倍,,
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 110000;
struct data {
int l, r;
long long sum;
long long lazy;
};
data p[maxn * 3];
int a[maxn];
int n, m;
int od, x, y, z;
void build(int x, int l, int r) {
p[x].l = l;
p[x].r = r;
if (p[x].l == p[x].r) {
p[x].sum = a[l];
return;
}
int mid = (l + r) >> 1;
build(2 * x, l, mid);
build(2 * x + 1, mid + 1, r);
p[x].sum = p[2 * x].sum + p[2 * x + 1].sum;
}
void update(int x) {
p[x].sum += p[x].lazy * (p[x].r - p[x].l + 1);
if (p[x].l == p[x].r) {
p[x].lazy = 0;
return;
}
p[2 * x].lazy += p[x].lazy;
p[2 * x + 1].lazy += p[x].lazy;
p[x].lazy = 0;
}
void change(int x, int l, int r, int z) {
if (p[x].l == l && p[x].r == r) {
p[x].lazy += z;
return;
}
if (p[x].lazy) update(x);
int mid = (p[x].l + p[x].r) >> 1;
if (r <= mid) change(2 * x, l, r, z);
else if (l > mid) change(2 * x + 1, l, r, z);
else {
change(2 * x, l, mid, z);
change(2 * x + 1, mid + 1, r, z);
}
p[x].sum = (p[2 * x].sum + p[2 * x + 1].sum + p[2 * x].lazy * (p[2 * x].r - p[2 * x].l + 1) + p[2 * x + 1].lazy * (p[2 * x + 1].r - p[2 * x + 1].l + 1));
}
long long xfind(int x, int l, int r) {
if (p[x].lazy) update(x);
if (p[x].l == l && p[x].r == r) {
return (p[x].sum);
}
int mid = (p[x].l + p[x].r) >> 1;
if (r <= mid) return (xfind(2 * x, l, r));
else if (l > mid) return (xfind(2 * x + 1, l, r));
else return (xfind(2 * x, l, mid) + xfind(2 * x + 1, mid + 1, r));
}
int main () {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
build(1, 1, n);
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &od, &x, &y);
if (od == 1) {
scanf("%d", &z);
change(1, x, y, z);
} else {
printf("%lld\n", xfind(1, x, y));
}
}
return 0;
}
单调队列:
传送门洛谷1886
改了一个世纪,,感觉单调队列有点虚,,错误点:
- q1和q2数组存储的应该是下标而非数据,处理过程中弄混
- 在前移队列尾指针时忘记控制尾指针小于头指针
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 1e6 + 500;
const int inf = 0x7fffffff;
int q1[maxn]; // min
int q2[maxn]; // max
int a[maxn];
int q1h = 1, q1t = 1;
int q2h = 1, q2t = 1;
int n, k;
int main () {
freopen("window.in", "r", stdin);
freopen("window.out", "w", stdout);
scanf("%d %d", &n, &k);
q2[0] = 0;
q1[0] = 0;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
q1[1] = 1;
for (int i = 2; i <= k; i++) {
while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
q1t++;
q1[q1t] = i;
}
printf("%d ", a[q1[1]]);
for (int i = k + 1; i <= n; i++) {
while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
q1t++;
q1[q1t] = i;
while (q1[q1h] <= i - k) q1h++;
printf("%d ", a[q1[q1h]]);
}
q2[1] = 1;
for (int i = 2; i <= k; i++) {
while (a[q2[q2t]] <= a[i] && q2t >= q2h) q2t--;
q2t++;
q2[q2t] = i;
}
printf("\n%d ", a[q2[1]]);
for (int i = k + 1; i <= n; i++) {
while(a[q2[q2t]] <= a[i] && q2t >= q2h) q2t--;
q2t++;
q2[q2t] = i;
while (q2[q2h] <= i - k) q2h++;
printf("%d ", a[q2[q2h]]);
}
return 0;
}
第二次做就熟悉了好多
传送门洛谷1440
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 2000000 + 5000;
int q1[maxn];
int q1h = 1, q1t = 1;
int n, m;
int a[maxn];
int main () {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
printf("0\n");
q1[1] = 1;
printf("%d\n", a[1]);
for (int i = 2; i <= m; i++) {
while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
q1t++;
q1[q1t] = i;
printf("%d\n", a[q1[1]]);
}
for (int i = m + 1; i < n; i++) {
while (a[q1[q1t]] >= a[i] && q1t >= q1h) q1t--;
q1t++;
q1[q1t] = i;
while (q1[q1h] <= i - m) q1h++;
printf("%d\n", a[q1[q1h]]);
}
return 0;
}
并查集:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 10000 + 500;
int father[maxn];
int x, y, od;
int n, m;
int getfather(int x) {
if (father[x] == x) return (x);
return (father[x] = getfather(father[x]));
}
int main () {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) father[i] = i;
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &od, &x, &y);
if (od == 1) {
int tx = getfather(x);
int ty = getfather(y);
if (tx == ty) continue;
father[tx] = ty;
} else {
int tx = getfather(x);
int ty = getfather(y);
if (tx == ty) printf("Y\n");
else printf("N\n");
}
}
return 0;
}
平衡树:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 100000 + 5000;
int size[maxn], left[maxn], right[maxn], val[maxn];
int n, m;
int tot = 0;
int t = 0;
int oop, key;
void right_rotate(int &t) {
int k = left[t];
left[t] = right[k];
right[k] = t;
size[k] = size[t];
size[t] = size[left[t]] + size[right[t]] + 1;
t = k;
}
void left_rotate(int &t) {
int k = right[t];
right[t] = left[k];
left[k] = t;
size[k] = size[t];
size[t] = size[left[t]] + size[right[t]] + 1;
t = k;
}
void maintain(int &t, bool flag) {
if (flag) {
if (size[right[right[t]]] > size[left[t]]) {
left_rotate(t);
} else if (size[left[right[t]]] > size[left[t]]) {
right_rotate(right[t]);
left_rotate(t);
} else return;
} else {
if (size[left[left[t]]] > size[right[t]]) {
right_rotate(t);
} else if (size[right[left[t]]] > size[right[t]]) {
left_rotate(left[t]);
right_rotate(t);
} else return;
}
maintain(left[t], 0);
maintain(right[t], 1);
maintain(t, 0);
maintain(t, 1);
}
void insert1(int &t, int v) {
if (t == 0) {
tot++;
t = tot;
size[t] = 1;
val[t] = v;
left[t] = 0;
right[t] = 0;
} else {
size[t]++;
if (v < val[t]) {
insert1(left[t], v);
} else {
insert1(right[t], v);
}
maintain(t, v >= val[t]);
}
}
int delete2(int &t, int v) {
int cur = 0;
size[t]--;
if (v == val[t] || (v > val[t] && right[t] == 0) || (v < val[t] && left[t] == 0)) {
cur = val[t];
if (left[t] == 0 || right[t] == 0) {
t = left[t] + right[t];
} else {
val[t] = delete2(left[t], v + 1);
}
} else if (v < val[t]) cur = delete2(left[t], v);
else cur = delete2(right[t], v);
return (cur);
}
int rank3(int &t, int v) {
if (t == 0) return (1);
if (val[t] >= v) {
return (rank3(left[t], v));
} else if (val[t] < v) {
return (rank3(right[t], v) + size[left[t]] + 1);
}
}
int find4(int &t, int v) {
if (size[left[t]] + 1 == v) return (val[t]);
else if (size[left[t]] + 1 < v) return (find4(right[t],v - size[left[t]] - 1));
else return (find4(left[t], v));
}
int pre5(int &t, int v) {
if (t == 0) return (-1);
if (v <= val[t]) {
return (pre5(left[t], v));
} else {
int cur = pre5(right[t], v);
if (cur == -1) return (val[t]);
return (cur);
}
}
int succ6(int &t, int v) {
if (t == 0) return (-1);
if (v >= val[t]) {
return (succ6(right[t], v));
} else {
int cur = succ6(left[t], v);
if (cur == -1) return (val[t]);
return (cur);
}
}
int main () {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d %d", &oop, &key);
if (oop == 1) insert1(t, key);
if (oop == 2) delete2(t, key);
if (oop == 3) printf("%d\n", rank3(t,key));
if (oop == 4) printf("%d\n", find4(t, key));
if (oop == 5) printf("%d\n", pre5(t, key));
if (oop == 6) printf("%d\n", succ6(t, key));
}
return 0;
}
算法
最小生成树
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 6000;
const int maxm = 210000;
struct data {
int from;
int to;
int val;
};
int father[maxn];
data p[maxm];
int n, m;
int x, y, z;
long long ans = 0;
int cur;
bool cmp(data aa, data bb) {
return (aa.val < bb.val);
}
int getfather(int x) {
if (father[x] == x) return (x);
return (father[x] = getfather(father[x]));
}
int main () {
scanf("%d %d", &n, &m);
cur = n;
for (int i = 1; i <= n; i++) father[i] = i;
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &p[i].from, &p[i].to, &p[i].val);
}
std :: sort(p + 1, p + m + 1, cmp);
for (int i = 1; i <= m; i++) {
int tx = getfather(p[i].from);
int ty = getfather(p[i].to);
if (tx != ty) {
cur--;
father[tx] = ty;
ans += p[i].val;
}
}
if (cur > 1) printf("orz");
else printf("%lld", ans);
return 0;
}
匈牙利算法:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 2200;
int line[maxn][maxn];
int flag[maxn];
int vis[maxn];
int n, m, e;
int ans = 0;
int x, y;
bool xfind(int x) {
for (int j = 1; j <= m; j++) {
if (line[x][j] && flag[j] == 0) {
flag[j] = 1;
if (vis[j] == 0 || xfind(vis[j])) {
vis[j] = x;
return 1;
}
}
}
return 0;
}
int main () {
scanf("%d %d %d", &n, &m, &e);
for (int i = 1; i <= e; i++) {
scanf("%d %d", &x, &y);
line[x][y] = 1;
}
for (int i = 1; i <= n; i++) {
memset(flag, 0, sizeof(flag));
if (xfind(i)) ans++;
}
printf("%d", ans);
return 0;
}
SPFA:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 15000;
const int maxm = 500000 + 5000;
const int inf = 0x7fffffff;
int dis[maxn], que[maxn], vis[maxn];
int last[maxn], pre[maxm], other[maxm], val[maxm];
int tot = 1;
int n, m, s;
int x, y, z;
void add(int x, int y, int z) {
tot++;
pre[tot] = last[x];
last[x] = tot;
other[tot] = y;
val[tot] = z;
}
void spfa(int s) {
que[1] = s;
for (int i = 1; i <= n; i++) dis[i] = inf;
dis[s] = 0;
int h = 0, t = 1;
while (h != t) {
h = (h + 1) % maxn;
int cur = que[h];
vis[cur] = 0;
for (int p = last[cur]; p; p = pre[p]) {
int q = other[p];
if (dis[q] > dis[cur] + val[p]) {
dis[q] = dis[cur] + val[p];
if (vis[q] == 0) {
vis[q] = 1;
t = (t + 1) % maxn;
que[t] = q;
}
}
}
}
}
int main () {
scanf("%d %d %d", &n, &m, &s);
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &x, &y, &z);
add(x, y, z);
}
spfa(s);
for (int i = 1; i <= n; i++) printf("%d ", dis[i]);
return 0;
}
堆+dijkstra:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxn = 12000;
const int maxm = 550000;
const int inf = 0x7fffffff;
int n, m;
int s;
int last[maxn], pre[maxm], other[maxm], len[maxm];
int dis[maxn];
bool vis[maxn];
int tot = 0;
int x, y, z;
struct point{
int dis;
int num;
point(int num, int dis) : dis(dis), num(num) {}
};
bool operator < (point aa, point bb) {
return (aa.dis > bb.dis);
}
std :: priority_queue <point> q1;
void add(int x, int y, int z) {
tot++;
pre[tot] = last[x];
last[x] = tot;
other[tot] = y;
len[tot] = z;
}
void dijkstra(int s) {
for (int i = 1; i <= n; i++) {
dis[i] = inf;
q1.push(point(i, dis[i]));
}
dis[s] = 0;
q1.push(point(s, dis[s]));
while (!q1.empty()) {
point kkk = q1.top();
q1.pop();
if (kkk.dis == inf) return;
if (vis[kkk.num]) continue;
vis[kkk.num] = 1;
for (int p = last[kkk.num]; p; p = pre[p]) {
int q = other[p];
if (dis[q] > dis[kkk.num] + len[p]) {
dis[q] = dis[kkk.num] + len[p];
q1.push(point(q, dis[q]));
}
}
}
}
int main () {
scanf("%d %d %d", &n, &m, &s);
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &x, &y, &z);
add(x, y, z);
}
dijkstra(s);
for (int i = 1; i <= n; i++) printf("%d ", dis[i]);
return 0;
}
KMP:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 1100000;
const int maxm = 1100;
int next[maxm];
char s1[maxn];
char s2[maxm];
int main () {
scanf("%s %s", s1, s2);
int len1 = strlen(s1);
int len2 = strlen(s2);
for (int i = 1, p = 0; i < len2; i++) {
while (s2[i] != s2[p] && p > 0) p = next[p-1];
if (s2[i] == s2[p]) p++;
next[i] = p;
}
for (int i = 0, p = 0; i < len1; i++) {
while (s1[i] != s2[p] && p > 0) p = next[p-1];
if (s1[i] == s2[p]) p++;
if (p == len2) {
printf("%d\n", i - len2 + 2);
p = next[p-1];
}
}
for (int i = 0; i < len2; i++) printf("%d ", next[i]);
return 0;
}
倍增LCA:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 550000;
int n, m, s;
int last[maxn], pre[maxn * 2], other[maxn * 2];
int jump[maxn][30];
int dis[maxn];
int tot = 0;
int x, y;
void add(int x, int y) {
tot++;
pre[tot] = last[x];
last[x] = tot;
other[tot] = y;
}
void dfs(int x, int come) {
jump[x][0] = come;
dis[x] = dis[come] + 1;
for (int p = last[x]; p; p = pre[p]) {
int q = other[p];
if (q == come) continue;
dfs(q, x);
}
}
int lca(int x, int y) {
if (dis[x] < dis[y]) std :: swap(x, y);
if (dis[x] != dis[y]) {
for (int j = 25; j >= 0; j--)
if (dis[jump[x][j]] > dis[y]) x = jump[x][j];
x = jump[x][0];
}
if (x == y) return (x);
for (int j = 25; j >= 0; j--) {
if (jump[x][j] != jump[y][j]) {
x = jump[x][j];
y = jump[y][j];
}
}
return jump[x][0];
}
int main () {
scanf("%d %d %d", &n, &m, &s);
for (int i = 1; i < n; i++) {
scanf("%d %d", &x, &y);
add(x, y);
add(y, x);
}
dfs(s, 0);
for (int i = 1; i <= 25; i++)
for (int j = 1; j <= n; j++)
jump[j][i] = jump[jump[j][i-1]][i-1];
for (int i = 1; i <= m; i++) {
scanf("%d %d", &x, &y);
printf("%d\n", lca(x, y));
}
return 0;
}
Tarjan求环:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 300000;
int next[maxn];
int dfn[maxn], low[maxn], size[maxn], belong[maxn];
bool vis[maxn];
int sta[maxn];
int statot = 0;
int cur = 0;
int tim = 0;
int n;
int ans = 0x7fffffff;
void tarjan(int x) {
tim++;
dfn[x] = low[x] = tim;
statot++;
vis[x] = 1;
sta[statot] = x;
int q = next[x];
if (!dfn[q]) {
tarjan(q);
low[x] = std :: min(low[x], low[q]);
} else if (vis[q]) {
low[x] = std :: min(dfn[q], low[x]);
}
if (dfn[x] == low[x]) {
cur++;
while (sta[statot] != x) {
belong[sta[statot]] = cur;
vis[sta[statot]] = 0;
size[cur]++;
statot--;
}
belong[x] = cur;
statot--;
size[cur]++;
}
}
int main () {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &next[i]);
for (int i = 1; i <= n; i++) {
if (!dfn[i]) tarjan(i);
}
for (int i = 1; i <= cur; i++) {
if (size[i] > 1) ans = std :: min(ans, size[i]);
}
printf("%d", ans);
return 0;
}
归并排序:
#include <cstdio>
#include <cstring>
#include <algorithm>
const int maxn = 100000 + 5000;
int tmp[maxn];
int a[maxn];
int n;
void merg(int *a, int l, int mid, int r) {
int cur = 1;
int k1 = l;
int k2 = mid + 1;
while (k1 <= mid && k2 <= r) {
if (a[k1] < a[k2]) {
tmp[cur] = a[k1];
cur++;
k1++;
} else {
tmp[cur] = a[k2];
cur++;
k2++;
}
}
while (k1 <= mid) {
tmp[cur] = a[k1];
cur++;
k1++;
}
while (k2 <= mid) {
tmp[cur] = a[k2];
k2++;
cur++;
}
memcpy(a + l, tmp + 1, sizeof(int) * (cur - 1));
}
void m_sort(int *a, int l, int r) {
if (l < r) {
int mid = (l + r) >> 1;
m_sort(a, l, mid);
m_sort(a, mid + 1, r);
merg(a, l, mid, r);
}
}
int main () {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
m_sort(a, 1, n);
for (int i = 1; i <= n; i++) printf("%d ", a[i]);
return 0;
}
网络流(dinic):
#include <cstdio>
#include <algorithm>
#include <cstring>
using std :: min;
const int maxm = 200000 + 1000;
const int maxn = 10000 + 500;
int last[maxn], pre[maxm], other[maxm], cap[maxm];
int tot = 1;
int s, t, n, m;
int x, y, z;
int dis[maxn], vis[maxn];
int que[maxn];
void add(int x, int y, int z) {
tot++;
pre[tot] = last[x];
last[x] = tot;
other[tot] = y;
cap[tot] = z;
}
bool bfs(void) {
memset(dis, 0, sizeof(dis));
memset(vis, 0, sizeof(vis));
int queh = 0, quet = 1;
que[1] = s;
vis[s] = dis[s] = 1;
while (queh < quet) {
queh++;
int cur = que[queh];
for (int p = last[cur]; p; p = pre[p]) {
int q = other[p];
if (cap[p] && !vis[q]) {
vis[q] = 1;
dis[q] = dis[cur] + 1;
quet++;
que[quet] = q;
}
}
}
return (dis[t] > 0);
}
int dinic(int x, int flow) {
if (x == t) return (flow);
int ret = 0;
for (int p = last[x]; p; p = pre[p]) {
int q = other[p];
if (cap[p] && flow && dis[q] == dis[x] + 1) {
int push = dinic(q, min(cap[p], flow));
if (!push) dis[q] = 0;
flow -= push;
ret += push;
cap[p] -= push;
cap[p ^ 1] += push;
}
}
return (ret);
}
int main () {
scanf("%d %d %d %d", &n, &m, &s, &t);
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &x, &y, &z);
add(x, y, z);
add(y, x, 0);
}
int ans = 0;
while (bfs()) {
ans += dinic(s, 0x7fffffff);
}
printf("%d\n", ans);
return 0;
}
字符串hash:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int mod = 1e7 + 19;
const int base = 31;
const int step = 72;
int hasht[mod];
char s[1600];
int n;
int ans = 0;
char hs[10005][1600];
int tot = 0;
int main () {
ios_base :: sync_with_stdio(0);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> s;
long long cur = 0;
int len = strlen(s);
for (int i = 0; i < len; i++) {
cur = (cur * base + (int)s[i]) % mod;
}
bool ft = 0;
while (hasht[cur] != 0) {
if (strcmp(hs[hasht[cur]], s) == 0) {
ft = 1;
break;
}
cur = (cur + step) % mod;
}
if (ft) continue;
tot++;
hasht[cur] = tot;
ans++;
strcpy(hs[tot], s);
}
cout << ans << endl;
return 0;
}