A 后缀数组
我字符串白给,有空补。
F 签到
题意:
给你两个字符串a,b,问你a的无限和b的无限字典序大小关系是什么。
思路:
大胆猜想,设a较长,把a扩大两
(或三)
倍,把b补齐,比较一下。
#include <bits/stdc++.h>
using namespace std;
const int maxn = (int)1e6 + 100;
string a, b, aa;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.precision(10);
cout << fixed;
#ifdef LOCAL_DEFINE
freopen("input.txt", "r", stdin);
#endif
while (cin >> a >> b) {
bool exchange = false;
if (int(a.size()) < int(b.size())) {
swap(a, b);
exchange = true;
}
aa = a;
aa += a;
bool big = false;
bool small = false;
int temp = int(b.size());
for (int i = 0; i < int(aa.size()); ++i) {
if (aa[i] > b[i % int(b.size())]) {
big = true;
break;
}
if (aa[i] < b[i % int(b.size())]) {
small = true;
break;
}
}
if (big) {
if (exchange) cout << "<" << '\n';
else cout << ">" << '\n';
} else if (small) {
if (exchange) cout << ">" << '\n';
else cout << "<" << '\n';
} else {
cout << "=" << '\n';
}
}
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}
H 费用流
题意:
有一个图,a,b,c表示一条流a->b流一个单位就要花费c元,现在有q个询问,问你如果要流u/v的总流到汇点,问你最少要花多少钱。
思路:
最小费用最大流,先乘上v再除以v就行了。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 200; //点数
const int INF = 0x3f3f3f3f;
struct Edge{
int from, to, cap, flow, cost;
Edge(int u, int v, int c, int f, int cc)
: from(u), to(v), cap(c), flow(f), cost(cc) {}
};
struct MCMF {
int n, m;
vector<Edge> edges;
vector<int> G[maxn];
vector< pair<ll, ll> > temp;
int inq[maxn]; //是否在队列中
int d[maxn]; //bellmanford
int p[maxn]; //上一条弧
int a[maxn]; //可改进量
void init(int n) {
this->n = n;
for (int i = 0; i <= n; ++i) G[i].clear();
edges.clear();
temp.clear(); //操操操,忘记初始化
}
void addEdge(int from, int to, int cap, int cost) {
edges.emplace_back(Edge(from, to, cap, 0, cost));
edges.emplace_back(Edge(to, from, 0, 0, -cost));
m = int(edges.size());
G[from].emplace_back(m - 2);
G[to].emplace_back(m - 1);
}
bool spfa(int s, int t, int &flow, ll &cost) {
for (int i = 1; i <= n; ++i) d[i] = INF;
memset(inq, 0, sizeof(inq));
d[s] = 0;
inq[s] = 1;
p[s] = 0;
queue<int> q;
a[s] = INF;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
inq[u] = 0;
for (int i = 0; i < int(G[u].size()); ++i) {
Edge &e = edges[G[u][i]];
if (e.cap > e.flow && d[e.to] > d[u] + e.cost) {
d[e.to] = d[u] + e.cost;
p[e.to] = G[u][i];
a[e.to] = min(a[u], e.cap - e.flow);
if (!inq[e.to]) {
q.push(e.to);
inq[e.to] = 1;
}
}
}
}
//if (d[t] > k) return false; //如果费用大于k就退出
//if (d[t] >= 0) return false; //最小费用流
if (d[t] == INF) return false;
flow += a[t];
cost += (ll)d[t] * (ll)a[t];
temp.emplace_back(make_pair(a[t], d[t]));
for (int u = t; u != s; u = edges[p[u]].from) {
edges[p[u]].flow += a[t];
edges[p[u] ^ 1].flow -= a[t];
}
return true;
}
int MincostMaxflow(int s, int t, ll &cost) {
int flow = 0;
cost = 0;
while (spfa(s, t, flow, cost));
return flow;
}
}mcmf;
int n, m, s, t;
bool cmp(pair<ll, ll> a, pair<ll, ll> b) {
return a.second < b.second;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.precision(10);
cout << fixed;
#ifdef LOCAL_DEFINE
freopen("input.txt", "r", stdin);
#endif
while (cin >> n >> m) {
mcmf.init(n + 10);
for (int i = 0; i < m; ++i) {
int u, v, f;
cin >> u >> v >> f;
mcmf.addEdge(u, v, 1, f);
}
ll cost = 0;
ll mf = mcmf.MincostMaxflow(1, n, cost);
// sort(mcmf.temp.begin(), mcmf.temp.end(), cmp);
int q;
cin >> q;
while (q--) {
ll u, v;
cin >> u >> v;
ll l = 0, r = v;
if (mf * u < v) {
cout << "NaN" << '\n';
continue;
}
ll sum = 0;
for (pair<int, int> now : mcmf.temp) {
if (sum + u * now.first <= v) {
sum += u * now.first;
l += now.first * now.second * u;
} else {
l += (v - sum) * now.second;
break;
}
}
ll tm = __gcd(l, r);
l /= tm; r /= tm;
cout << l << '/' << r << '\n';
}
}
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}
I 一般图最大匹配
1 or 2
题意:
有一个m条边n个点的无向有环图,给你一个数组di表示第i个顶点的出度是d[i],现在让你删某些边,然后满足这个数组d。
思路:
一般图最大匹配,拆顶点表示度数,拆边连顶点。
最后看是不是所有点都能连到,也就是看连的边数*2是不是等于所有的点数就行。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1100;
int n, m, x, y, tot, d[maxn], sum;
vector<int> G[maxn];
namespace Blossom {
int mate[maxn], n, ret, nxt[maxn], f[maxn], mark[maxn], vis[maxn], t;
queue<int> q;
int F(int x) {return x == f[x] ? x : f[x] = F(f[x]);}
void Merge(int a, int b) {f[F(a)] = F(b);}
int lca(int x, int y) {
for (t++;;swap(x, y)) {
if (~x) {
if (vis[x = F(x)] == t) return x;
vis[x] = t;
x = (mate[x] != -1 ? nxt[mate[x]] : -1);
}
}
}
void group(int a, int p) {
for (int b, c; a != p; Merge(a, b), Merge(b, c), a = c) {
b = mate[a], c = nxt[b];
if (F(c) != p) nxt[c] = b;
if (mark[b] == 2) mark[b] = 1, q.push(b);
if (mark[c] == 2) mark[c] = 1, q.push(c);
}
}
void aug(int s, const vector<int> G[]) {
for (int i = 0; i < n; ++i) {
nxt[i] = vis[i] = -1;
f[i] = i;
mark[i] = 0;
}
while (!q.empty()) q.pop();
q.push(s);
mark[s] = 1;
while (mate[s] == -1 && !q.empty()) {
int x = q.front();
q.pop();
for (int i = 0, y; i < int(G[x].size()); ++i) {
if ((y = G[x][i]) != mate[x] && F(x) != F(y) && mark[y] != 2) {
if (mark[y] == 1) {
int p = lca(x, y);
if (F(x) != p) nxt[x] = y;
if (F(y) != p) nxt[y] = x;
group(x, p); group(y, p);
} else if (mate[y] == -1) {
nxt[y] = x;
for (int j = y, k, l; ~j; j = l) {
k = nxt[j];
l = mate[k];
mate[j] = k;
mate[k] = j;
}
break;
} else {
nxt[y] = x;
q.push(mate[y]);
mark[mate[y]] = 1;
mark[y] = 2;
}
}
}
}
}
void solve(int _n, vector<int> G[]) {
n = _n;
memset(mate, -1, sizeof(mate));
for (int i = t =0 ; i < n; ++i) if (mate[i] == -1) aug(i, G);
for (int i = ret = 0; i < n; ++i) ret += (mate[i] > i);
if (ret * 2 == sum) {
cout << "Yes" << '\n';
} else {
cout << "No" << '\n';
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.precision(10);
cout << fixed;
#ifdef LOCAL_DEFINE
freopen("input.txt", "r", stdin);
#endif
while (cin >> n >> m) {
tot = 2 * n;
for (int i = 0; i <= 1000; ++i) G[i].clear();
sum = 2 * m;
for (int i = 1; i <= n; ++i) {
cin >> d[i];
sum += d[i];
}
for (int i = 0; i < m; ++i) {
int u, v;
cin >> u >> v;
--u; --v;
int a1 = tot++, a2 = tot++;
G[a1].emplace_back(a2);
G[a2].emplace_back(a1);
G[u].emplace_back(a1);
G[a1].emplace_back(u);
if (d[u + 1] == 2) {
G[u + n].emplace_back(a1);
G[a1].emplace_back(u + n);
}
G[v].emplace_back(a2);
G[a2].emplace_back(v);
if (d[v + 1] == 2) {
G[v + n].emplace_back(a2);
G[a2].emplace_back(v + n);
}
}
Blossom::solve(1000, G);
}
#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}