高斯消元
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
int n;
double a[23][23], b[23], c[23][23], temp;
int main() {
scanf("%d", &n);
for(int i = 1; i <= n + 1; i++)
for(int j = 1; j <= n; j++)
scanf("%lf", &a[i][j]);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
c[i][j] = 2 * (a[i][j] - a[i + 1][j]);
b[i] += a[i][j] * a[i][j] - a[i + 1][j] * a[i + 1][j];
}
for(int i = 1; i <= n; i++)
{
for(int j = i; j <= n; j++)
{
if(fabs(c[j][i]) > 1e-8)
{
for(int k = 1; k <= n; k++)
swap(c[i][k], c[j][k]);
swap(b[i], b[j]);
}
}
for(int j = 1; j <= n; j++)
{
if(i == j) continue;
temp = c[j][i] / c[i][i];
for(int k = i; k <= n; k++)
c[j][k] -= c[i][k] * temp;
b[j] -= b[i] * temp;
}
}
for(int i = 1; i <= n; i++)
printf("%0.3lf ", b[i] / c[i][i]);
return 0;
}
并查集
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n, m, dad[10007];
int find(int x)
{
if(dad[x] != x) return dad[x] = find(dad[x]);
return x;
}
void uni(int x, int y)
{
int r1 = find(x);
int r2 = find(y);
if(r1 != r2)
dad[r1] = r2;
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
dad[i] = i;
for(int i = 1; i <= m; i++)
{
int x, y, op;
scanf("%d%d%d", &op, &x, &y);
if(op == 1)
uni(x, y);
else if(op == 2)
{
int r1 = find(x);
int r2 = find(y);
if(r1 != r2)
printf("N\n");
else printf("Y\n");
}
}
return 0;
}
离散化
sort(hash + 1, hash + 1 + n);
int siz =unique(hash + 1, hash + 1 + n) - hash - 1;
线段树
#include <cstdio>
#include <algorithm>
#include <cstring>
typedef int int_;
#define int long long
using namespace std;
int tree[800007], lazy[800007];
int n, m;
void pushup(int o)
{
tree[o] = tree[o << 1] + tree[o << 1 | 1];
}
void pushdown(int o, int l, int r)
{
if(!lazy[o]) return ;
int mid = (l + r) >> 1;
tree[o << 1] += lazy[o] * (mid - l + 1);
tree[o << 1 | 1] += lazy[o] * (r - mid);
lazy[o << 1] += lazy[o];
lazy[o << 1 | 1] += lazy[o];
lazy[o] = 0;
}
void build(int o, int l, int r)
{
if(l == r)
{
int x;
scanf("%lld", &x);
tree[o] = x;
return ;
}
int mid = (l + r) >> 1;
build(o << 1, l, mid);
build(o << 1 | 1, mid + 1, r);
pushup(o);
}
void update(int o, int l, int r, int ql, int qr, int k)
{
if(ql <= l && qr >= r)
{
tree[o] += k * (r - l + 1);
lazy[o] += k;
return ;
}
pushdown(o, l, r);
int mid = (l + r) >> 1;
if(ql <= mid) update(o << 1, l, mid, ql, qr, k);
if(qr > mid) update(o << 1 | 1, mid + 1, r, ql, qr, k);
pushup(o);
}
int query(int o, int l, int r, int ql, int qr)
{
if(ql <= l && qr >= r) return tree[o];
pushdown(o, l, r);
int mid = (l + r) >> 1, ret = 0;
if(ql <= mid) ret += query(o << 1, l, mid, ql, qr);
if(qr > mid) ret += query(o << 1 | 1, mid + 1, r, ql, qr);
return ret;
}
int_ main() {
int x, y, op, k;
scanf("%lld%lld", &n, &m);
build(1, 1, n);
for(int i = 1; i <= m; i++)
{
scanf("%lld", &op);
if(op == 1)
{
scanf("%lld%lld%lld", &x, &y, &k);
update(1, 1, n, x, y, k);
}
else
{
scanf("%lld%lld", &x, &y);
printf("%lld\n", query(1, 1, n, x, y));
}
}
return 0;
}
主席树
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int a[200007], hash[200007], T[200007], L[200007 << 5], R[200007 << 5], sum[200007 << 5];
int n, m, ncnt;
int build(int l, int r)
{
int num = ++ncnt;
if(l != r)
{
int mid = (l + r) >> 1;
L[num] = build(l, mid);
R[num] = build(mid + 1, r);
}
return num;
}
int update(int o, int l, int r, int x)
{
int num = ++ncnt;
L[num] = L[o], R[num] = R[o], sum[num] = sum[o] + 1;
if(l != r)
{
int mid = (l + r) >> 1;
if(x <= mid) L[num] = update(L[o], l, mid, x);
else R[num] = update(R[o], mid + 1, r, x);
}
return num;
}
int query(int u, int v, int l, int r, int k)
{
if(l == r) return hash[l];
int num = sum[L[v]] - sum[L[u]];
int mid = (l + r) >> 1;
if(num >= k) return query(L[u], L[v], l, mid, k);
else return query(R[u], R[v], mid + 1, r, k - num);
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
hash[i] = a[i];
}
sort(hash + 1, hash + 1 + n);
int siz =unique(hash + 1, hash + 1 + n) - hash - 1;
T[0] = build(1, siz);
for(int i = 1; i <= n; i++)
{
int x = lower_bound(hash + 1, hash + 1 + siz, a[i]) - hash;
T[i] = update(T[i - 1], 1, siz, x);
}
int l, r, k;
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d", &l, &r, &k);
printf("%d\n", query(T[l - 1], T[r], 1, siz, k));
}
return 0;
}
LCA
//倍增
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 600010
using namespace std;
int cnt, n, m, deep[maxn], dp[maxn][21], head[maxn];
struct node{
int v, next;
}e[maxn << 1];
void add(int u, int v)
{
e[++cnt].v = v;
e[cnt].next = head[u];
head[u] = cnt;
}
void dfs(int x, int fa)
{
deep[x] = deep[fa] + 1;
dp[x][0] = fa;
for(int i = head[x]; i; i = e[i].next)
{
int v = e[i].v;
if(v != fa)
dfs(v, x);
}
}
void init()
{
for(int j = 1; (1 << j) <= n; j++)
{
for(int i = 1; i <= n; i++)
if(deep[i] >= (1 << j))
dp[i][j] = dp[dp[i][j - 1]][j - 1];
}
}
int lca(int x, int y)
{
if(deep[x] < deep[y]) swap(x, y);
int d = deep[x] - deep[y];
for(int j = 20; j >= 0; j--) if(d & (1 << j)) x = dp[x][j];
if(x == y)
return x;
for(int i = 20; i >= 0; i--)
{
if(dp[x][i] != dp[y][i])
{
x = dp[x][i];
y = dp[y][i];
}
}
return dp[x][0];
}
int main() {
int rt, x, y;
scanf("%d%d%d", &n, &m, &rt);
for(int i = 1; i < n; i++)
{
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
dfs(rt, 0);
init();
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &x, &y);
printf("%d\n", lca(x, y));
}
return 0;
}
tarjan
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;
int n, m, flag;
struct node {
int v, next;
}e[50009];
int head[50009], cnt;
void add(int u, int v)
{
e[++cnt].v = v;
e[cnt].next = head[u];
head[u] = cnt;
}
int vis[10009], tot, ctot, now, num[10009], ran[10009];\
int dfn[10009], low[10009];
stack<int> s;
void tarjan(int x)
{
vis[x] = 1;
s.push(x);
dfn[x] = low[x] = ++tot;
for(int i = head[x]; i; i = e[i].next) {
int v = e[i].v;
if(!dfn[v]) {
tarjan(v);
low[x] = min(low[x], low[v]);
}
else if(vis[v]) {
low[x] = min(low[x], dfn[v]);
}
}
if(dfn[x] == low[x]) {
ctot++;
now = -1;
while(now != x) {
now = s.top();
s.pop();
vis[now] = 0;
ran[now] = ctot;
num[ctot]++;
}
}
}
int cd[10009];
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
}
for(int i = 1; i <= n; i++) {
if(!dfn[i]) tarjan(i);
}
for(int i = 1; i <= n; i++) {
for(int j = head[i]; j; j = e[j].next) {
int v = e[j].v;
if(ran[i] != ran[v]) {
cd[ran[i]] += 1;
}
}
}
for(int i = 1; i <= ctot; i++) {
if(!cd[i]) {
if(flag) {
printf("0");
return 0;
}
flag = i;
}
}
printf("%d", num[flag]);
return 0;
}
2 缩点【模板】缩点
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#define maxn 100010
using namespace std;
int n, m, u, v, head[maxn], HEAD[maxn], dfn[maxn], low[maxn], vis[maxn], cnt;
int now, tot, jh[maxn], VAL[maxn], val[maxn], rd[maxn], dp[maxn], ans;
stack<int> s;
queue<int> q;
struct node{
int v, next;
}e[100010], E[100010];
void add(int u, int v)
{
e[++cnt].v = v;
e[cnt].next = head[u];
head[u] = cnt;
}
void ADD(int u, int v)
{
E[++cnt].v = v;
E[cnt].next = HEAD[u];
HEAD[u] = cnt;
}
void tarjan(int x)
{
dfn[x] = low[x] = ++cnt;
s.push(x);
vis[x] = 1;
for(int i = head[x]; i; i = e[i].next)
{
int v = e[i].v;
if(!dfn[v])
{
tarjan(v);
low[x] = min(low[x], low[v]);
}
else if(vis[v])
low[x] = min(low[x], dfn[v]);
}
if(dfn[x] == low[x])
{
now = -1;
tot++;
while(now != x)
{
now = s.top();
s.pop();
jh[now] = tot;
VAL[tot] += val[now];
vis[now] = 0;
}
}
}
void rebuild()
{
for(int x = 1; x <= n; x++)
{
for(int i = head[x]; i; i = e[i].next)
{
int v = e[i].v;
if(jh[x] != jh[v])
{
ADD(jh[x], jh[v]);
rd[jh[v]]++;
}
}
}
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
scanf("%d", &val[i]);
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &u, &v);
add(u, v);
}
cnt = 0;
for(int i = 1; i <= n; i++)
if(!dfn[i]) tarjan(i);
cnt = 0;
rebuild();
for(int i = 1; i <= tot; i++)
{
if(!rd[i])
{
q.push(i);
dp[i] = VAL[i];
}
}
while(!q.empty())
{
int x = q.front();
q.pop();
for(int i = HEAD[x]; i; i = E[i].next)
{
int v = E[i].v;
dp[v] = max(dp[v], dp[x] + VAL[v]);
rd[v]--;
if(!rd[v]) q.push(v);
}
}
for(int i = 1; i <= tot; i++) ans = max(ans, dp[i]);
printf("%d", ans);
return 0;
}
3割点【模板】割点(割顶)
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n, m, cnt, rt, vis[20050], dfn[20050], low[20050], head[20050], son, ans[20050], tot;
struct node{
int v, next;
}e[200050];
void add(int u, int v)
{
e[++cnt].v = v;
e[cnt].next = head[u];
head[u] = cnt;
}
void tarjan(int x, int f)
{
low[x] = dfn[x] = ++cnt;
for(int i = head[x]; i; i = e[i].next)
{
int v = e[i].v;
if(!dfn[v])
{
tarjan(v, x);
low[x] = min(low[x], low[v]);
if(low[v] >= dfn[x])
{
if(x == rt) son++;
else if(!ans[x])
{
ans[x] = 1;
tot++;
}
}
}
else if(v != f) low[x] = min(low[x], dfn[v]);
}
}
int main() {
int u, v;
scanf("%d%d", &n, &m);
while(m--)
{
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
cnt = 0;
for(int i = 1; i <= n; i++)
{
if(!dfn[i]) tarjan(rt = i, 0);
if(son >= 2)
{
ans[rt] = 1;
tot++;
}
son = 0;
}
printf("%d\n", tot);
for(int i = 1; i <= n; i++)
if(ans[i])
printf("%d ", i);
return 0;
}
最短路
dijkstra【模板】单源最短路径(标准版)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define INF 2147483647
#define maxn 1000010
using namespace std;
int n, m, s, dis[maxn], vis[maxn];
int u, v, val, head[maxn], cnt;
priority_queue<pair<int, int> > q;
struct node{
int v, val, next;
}e[maxn << 1];
void add(int u, int v, int val)
{
e[++cnt].v = v;
e[cnt].val = val;
e[cnt].next = head[u];
head[u] = cnt;
}
void dijkstra()
{
for(int i = 1; i <= n; i++) dis[i] = INF;
dis[s] = 0;
q.push(make_pair(0, s));
while(!q.empty())
{
int x = q.top().second;
q.pop();
if(vis[x]) continue;
vis[x] = 1;
for(int i = head[x]; i; i = e[i].next)
{
int v = e[i].v, val = e[i].val;
if(!vis[v] && dis[v] > dis[x] + val)
{
dis[v] = dis[x] + val;
q.push(make_pair(-dis[v], v));
}
}
}
}
int main() {
scanf("%d%d%d", &n, &m, &s);
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d", &u, &v, &val);
add(u, v, val);
}
dijkstra();
for(int i = 1; i <= n; i++)
printf("%d ", dis[i]);
return 0;
}
SPFA【模板】单源最短路径(弱化版)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define INF 2147483647
using namespace std;
int n, s, m, cnt, head[10007], dis[10007], vis[10007];
struct node{
int v, next, val;
}edge[500007];
void add(int u, int v, int val)
{
edge[++cnt].v = v;
edge[cnt].val = val;
edge[cnt].next = head[u];
head[u] = cnt;
}
void spfa()
{
queue<int> q;
for(int i = 1; i <= n; i++) dis[i] = INF;
dis[s] = 0;
q.push(s);
while(!q.empty())
{
int x = q.front();
q.pop();
vis[x] = 0;
for(int i = head[x]; i; i = edge[i].next)
{
int v = edge[i].v, val = edge[i].val;
if(dis[v] > dis[x] + val)
{
dis[v] = dis[x] + val;
if(!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
}
int main() {
int u, v, val;
scanf("%d%d%d", &n, &m, &s);
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d", &u, &v, &val);
add(u, v, val);
}
spfa();
for(int i = 1; i <= n; i++)
printf("%d ", dis[i]);
return 0;
}
Floyd P1119 灾后重建
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[205][205], n, m, k, q, mp[205];
int main() {
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
dp[i][j] = 1e9 + 7;
dp[i][i] = 0;
}
for(int i = 0; i < n; i++) scanf("%d", &mp[i]);
for(int i = 1; i <= m; i++)
{
int u, v, val;
scanf("%d%d%d", &u, &v, &val);
dp[u][v] = dp[v][u] = min(dp[u][v], val);
}
scanf("%d", &q);
for(int wt = 1; wt <= q; wt++)
{
int qa, qb, qt;
scanf("%d%d%d", &qa, &qb, &qt);
while(mp[k] <= qt && k < n)
{
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
k += 1;
}
if(dp[qa][qb] >= 1e9 + 7 || mp[qa] > qt || mp[qb] > qt)
printf("-1\n");
else printf("%d\n", dp[qa][qb]);
}
}
差分约束系统
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
const int INF = 1e9 + 7;
using namespace std;
int n, m;
int cnt1, cnt2, cnt;
int head1[2009], head2[2009], head[2009];
struct node {
int u, v, next, val;
}e1[2009], e2[2009], e[2009];
void add1(int u, int v) {
e1[++cnt1].v = v;
e1[cnt1].u = u;
e1[cnt1].next = head1[u];
head1[u] = cnt1;
}
void add2(int u, int v) {
e2[++cnt2].v = v;
e2[cnt2].next = head2[u];
head2[u] = cnt2;
}
void add(int u, int v, int val) {
e[++cnt].v = v;
e[cnt].u = u;
e[cnt].val = val;
e[cnt].next = head[u];
head[u] = cnt;
}
int vis1[1009], vis2[1009];
void dfs1(int x) {
vis1[x] = 1;
for(int i = head1[x]; i; i = e1[i].next) {
int v = e1[i].v;
if(vis1[v]) continue;
vis1[v] = 1;
dfs1(v);
}
return ;
}
void dfs2(int x)
{
vis2[x] = 1;
for(int i = head2[x]; i; i = e2[i].next) {
int v = e2[i].v;
if(vis2[v]) continue;
vis2[v] = 1;
dfs2(v);
}
return ;
}
int dis[1009], vis[1009], scnt[1009];
int spfa(int x) {
queue<int> q;
for(int i = 1; i <= n; i++) dis[i] = INF;
q.push(x);
vis[x] = 1;
dis[x] = 0;
scnt[x] = 1;
while(!q.empty()) {
x = q.front();
q.pop();
vis[x] = 0;
for(int i = head[x]; i; i = e[i].next) {
int v = e[i].v, val = e[i].val;
if(dis[v] > dis[x] + val) {
dis[v] = dis[x] + val;
scnt[v]++;
if(scnt[v] > n) {
return -1;
}
if(!vis[v]) {
vis[v] = 1;
q.push(v);
}
}
}
}
return 0;
}
int jud[1009];
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
add1(u, v), add2(v, u);
}
dfs1(1);
dfs2(n);
for(int i = 1; i <= n; i++) {
if(vis1[i] && vis2[i]) {
jud[i] = 1;
add(0, i, 0);
}
}
if(!jud[n]) {
printf("-1");
return 0;
}
for(int i = 1; i <= m; i++) {
int u = e1[i].u, v = e1[i].v;
if(!(jud[u] && jud[v])) continue;
add(u, v, 9);
add(v, u, -1);
}
if(spfa(1) == -1) {
printf("-1");
return 0;
}
printf("%d %d\n", n, m);
for(int i = 1; i <= m; i++) {
int u = e1[i].u, v = e1[i].v;
printf("%d %d ", u, v);
if(!(jud[u] && jud[v])) printf("1\n");
else printf("%d\n", dis[v] - dis[u]);
}
return 0;
}
最小生成树
最小生成树P1195 口袋的天空
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node{
int a,b,c;
}l[100005];
int dad[1006];
int cmp(const node s1,const node s2)
{
return s1.c < s2.c;
}
int find(int x)
{
if(dad[x] != x) return dad[x] = find(dad[x]);
return x;
}
int main() {
int n,m,ans = 0,k = 0,r;
scanf("%d%d%d",&n,&m,&r);
for(int i = 1; i <= n; i++) dad[i] = i;
for(int i = 1; i <= m; i++)
scanf("%d%d%d",&l[i].a,&l[i].b,&l[i].c);
sort(l + 1,l + 1 + m, cmp);
for(int i = 1; i <= m; i++)
{
int r1 = find(l[i].a);
int r2 = find(l[i].b);
if(r1 != r2)
{
dad[r2] = r1;
k++;
ans += l[i].c;
}
if(k == n-r)
{
printf("%d",ans);
return 0;
}
}
printf("No Answer");
return 0;
}
HASH
#include <cstdio>
#include <cstring>
#include <algorithm>
unsigned long long s[10010];
char a[10010];
unsigned long long hashh(char x[])
{
int len = strlen(x);
unsigned long long temp = 0;
for(int i = 0; i < len; i++)
{
temp = (temp * 13331 + (unsigned long long)x[i]);
}
return temp;
}
int main() {
int n,ans = 1;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
{
scanf("%s",a);
s[i] = hashh(a);
}
std::sort(s + 1,s + n + 1);
for(int i = 2; i <= n; i++)
if(s[i] != s[i - 1]) ans++;
printf("%d\n",ans);
return 0;
}