先放课程表:
统计单词数(word.cpp/word.in/word.out):
This is a test. This test is easy. This is a test. This test is easy.
THIS:4
IS:4
A:**2
TEST:**4
EASY:**2
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 110;
const int MAXL = 30;
bool isAlpha(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
char upper(char c) {
return (c >= 'a' && c <= 'z')? c - 'a' + 'A': c;
}
string getWord() {
char c = '\0';
string s = "";
while (!isAlpha(c)) {
if (c == '\n') return s;
c = cin.get();
}
s += upper(c);
while (c = cin.get(), isAlpha(c))
s += upper(c);
return s;
}
int cnt, freq[MAXN];
string dict[MAXN];
int main() {
int r, maxl = 0;
string t;
freopen("word.in", "r", stdin);
freopen("word.out", "w", stdout);
while (t = getWord(), t != "") {
r = 0;
for (int i = 1; i <= cnt; i++)
if (dict[i] == t) {
r = i; break;
}
if (r) { freq[r]++; continue; }
dict[++cnt] = t;
freq[cnt] = 1;
maxl = max(maxl, (int)t.length());
}
for (int i = 1; i <= cnt; i++) {
for (int j = 1; j <= maxl - dict[i].length(); j++)
cout << ' ';
cout << dict[i] << ":";
for (int j = 1; j <= freq[i]; j++)
cout << '*';
cout << freq[i] << endl;
}
fclose(stdin);
fclose(stdout);
return 0;
}
数的读法(num.cpp/num.in/num.out):
1234567009
shi er yi san qian si bai wu shi liu wan qi qian ling jiu
1、 数的开头不允许有零
2、 不允许有相邻的零
3、 不允许出现“零亿”、“零万”
4、数的开头不允许出现“一十”,而要用“十”代替
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const string p[10] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
ll n;
string outp[10000];
int cnt = 0;
bool flag_yi[10000];
void read(ll x) {
if (x / 1000) {
outp[++cnt] = p[x / 1000];
outp[++cnt] = "qian";
} else
outp[++cnt] = "ling";
x %= 1000;
if (x / 100) {
outp[++cnt] = p[x / 100];
outp[++cnt] = "bai";
} else
outp[++cnt] = "ling";
x %= 100;
if (x / 10) {
outp[++cnt] = p[x / 10];
outp[++cnt] = "shi";
} else
outp[++cnt] = "ling";
x %= 10;
if (x != 0)
outp[++cnt] = p[x];
}
int main() {
freopen("num.in", "r", stdin);
freopen("num.out", "w", stdout);
cin >> n;
if (n / 100000000) {
read(n / 100000000); n %= 100000000;
outp[++cnt] = "yi", flag_yi[cnt] = 1;
}
if (n / 10000) {
read(n / 10000); n %= 10000;
outp[++cnt] = "wan";
}
if (n) read(n);
while (outp[cnt] == "ling") cnt--;
bool start = 1;
outp[0] = "ling";
for (int i = 1; i <= cnt; i++)
if (outp[i] == "ling") {
if (outp[i - 1] != "ling" && (outp[i + 1] != "yi" || !flag_yi[i + 1]) && outp[i + 1] != "wan")
cout << outp[i] << " ", start = 0;
} else if (outp[i] == "yi") {
if (!(start && outp[i + 1] == "shi"))
cout << outp[i] << " ", start = 0;
} else
cout << outp[i] << " ", start = 0;
cout << endl;
fclose(stdin);
fclose(stdout);
return 0;
}
算术杀手(killer.cpp/killer.in/killer.out):
32 + 99
-3 * -6
-2 + -3
2 - 3
131
18
-5
-1
对于第1,2,3组数据,输入不包含乘法算式
对于第4,5组数据,a,b在int范围内
对于第6,7组数据,输入不包含减法算式,且a,b为非负数
对于第8,9,10组数据,无特殊限制
#include <bits/stdc++.h>
using namespace std;
const int MAXL = 2e3 + 10;
struct bigNum {
int d[MAXL], len;
bigNum() {
len = 0;
}
bigNum(const bigNum &t) {
len = t.len;
memcpy(d, t.d, sizeof(d));
}
bigNum(const string &s) {
len = s.length();
for (int i = 0; i < len; i++)
d[i] = s[len - i - 1] - '0';
}
void operator +=(bigNum &t) {
if (len < t.len) {
for (int i = len; i < t.len; i++)
d[i] = 0;
len = t.len;
}
for (int i = 0; i < len; i++) {
if (i < t.len)
d[i] += t.d[i];
if (d[i] >= 10) {
if (i == len - 1)
d[len] = 0, len++;
d[i + 1]++, d[i] -= 10;
}
}
}
void operator -=(bigNum &t) {
for (int i = 0; i < len; i++) {
if (i < t.len)
d[i] -= t.d[i];
if (d[i] < 0)
d[i + 1]--, d[i] += 10;
}
while (len > 0 && d[len - 1] == 0)
len--;
}
bigNum operator +(bigNum &t) {
bigNum a(*this);
a += t;
return a;
}
bigNum operator -(bigNum &t) {
bigNum a(*this);
a -= t;
return a;
}
bigNum operator *(bigNum &t) {
bigNum res;
memset(res.d, 0, sizeof(res.d));
res.len = len + t.len - 1;
for (int i = 0; i < len; i++)
for (int j = 0; j < t.len; j++)
res.d[i + j] += d[i] * t.d[j];
for (int i = 0; i < res.len; i++)
if (res.d[i] / 10) {
res.d[i + 1] += res.d[i] / 10;
res.d[i] %= 10;
if (i == res.len - 1) res.len++;
}
return res;
}
bool operator <(bigNum &t) {
if (len != t.len)
return len < t.len;
for (int i = len - 1; i >= 0; i--)
if (d[i] != t.d[i])
return d[i] < t.d[i];
return 0;
}
friend ostream &operator <<(ostream &out, const bigNum &t) {
if (t.len == 0)
out << 0;
for (int i = t.len - 1; i >= 0; i--)
out << t.d[i];
return out;
}
};
void work(bigNum &a, bigNum &b) { // 输出 a - b 的结果
if (a < b)
cout << "-" << b - a;
else
cout << a - b;
}
int main() {
string s, t;
char op;
freopen("killer.in", "r", stdin);
freopen("killer.out", "w", stdout);
while (cin >> s >> op >> t) {
int sgna = 1, sgnb = 1;
if (s[0] == '-')
sgna = -1, s = s.substr(1, s.length() - 1);
if (t[0] == '-')
sgnb = -1, t = t.substr(1, t.length() - 1);
bigNum a(s), b(t);
if (op == '*') {
if (sgna != sgnb)
cout << "-";
cout << a * b;
} else if (op == '+') {
if (sgna == sgnb) {
if (sgna == -1)
cout << "-";
cout << a + b;
} else {
if (sgna == 1)
work(a, b);
else
work(b, a);
}
} else { // op = '-'
if (sgna != sgnb) {
if (sgna == -1)
cout << "-";
cout << a + b;
} else {
if (sgna == 1) // a - b
work(a, b);
else // (-a) - (-b) = b - a
work(b, a);
}
}
cout << endl;
}
fclose(stdin);
fclose(stdout);
return 0;
}
基本概念:
$Prim$算法:
算法:设原图点集为$V$,$A$为已在生成树中的点构成的集合。
并查集:
算法:用一个树形结构维护一个集合,初始时每个节点单独成一棵树,只需记录每个点的父节点,初始化 $fa[i] = i (1\leq i\leq n)$。
int find(int x) { // 查找 x 所在树的根节点
if (fa[x] == x)
return x;
else
return find(fa[x]);
}
bool query(int u, int v) { // 查询 u 和 v 是否在同一集合
return (find(u) == find(v));
}
void merge(int u, int v) { // 合并 u 和 v 所在集合
u = find(u), v = find(v);
fa[u] = v;
}
int find(int x) { //路径压缩
if (fa[x] == x) return x;
fa[x] = find(fa[x]);
return fa[x];
}
int find(int x) {
return (fa[x] == x)? x: (fa[x] = find(fa[x]));
}
时间复杂度:
$Kruskal$算法:
算法:
用并查集维护点之间的连通性,对于一条边,查询两端点是否属于同一集合,若是,则会产生环,不能选;若不是,则可以选择。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e3 + 10;
const int MAXM = 4e5 + 10;
struct edge {
int v, w, next;
};
int n, m, head[MAXN], size;
edge e[MAXM];
int dis[MAXN], flag[MAXN];
void addEdge(int u, int v, int w) {
e[size].v = v;
e[size].w = w;
e[size].next = head[u];
head[u] = size;
size++;
}
int main() {
memset(head, -1, sizeof(head));
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
addEdge(u, v, w);
addEdge(v, u, w);
}
for (int i = 1; i <= n; i++)
dis[i] = 1 << 30;
flag[1] = 1;
for (int i = head[1]; i != -1; i = e[i].next)
dis[e[i].v] = min(dis[e[i].v], e[i].w);
int ans = 0;
for (int i = 1; i <= n - 1; i++) {
int md = 1 << 30, v = -1;
for (int j = 1; j <= n; j++)
if (!flag[j] && dis[j] < md)
md = dis[j], v = j;
if (v == -1) {
cout << "orz" << endl;
exit(0);
}
flag[v] = 1;
ans += md;
for (int j = head[v]; j != -1; j = e[j].next)
dis[e[j].v] = min(dis[e[j].v], e[j].w);
}
cout << ans << endl;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e3 + 10;
const int MAXM = 2e5 + 10;
struct edge {
int u, v, w;
};
bool cmp(const edge &a, const edge &b) {
return a.w < b.w;
}
int n, m, fa[MAXN];
edge e[MAXM];
int find(int x) {
return fa[x] == x? x: fa[x] = find(fa[x]);
}
int main() {
cin >> n >> m;
for (int i = 1; i <= m; i++)
cin >> e[i].u >> e[i].v >> e[i].w;
sort(e + 1, e + m + 1, cmp);
int cnt = 0, ans = 0;
for (int i = 1; i <= n; i++)
fa[i] = i;
for (int i = 1; i <= m && cnt < n - 1; i++)
if (find(e[i].u) != find(e[i].v)) {
cnt++;
ans += e[i].w;
fa[find(e[i].u)] = find(e[i].v);
}
if (cnt == n - 1)
cout << ans << endl;
else
cout << "orz" << endl;
return 0;
}
今天讲了最小生成树和并查集,图论中的基本算法应该差不多就是(最短路+最小生成树+强连通分量+........)。还有3天,就可以过年了。我好认真啊,竟然写了3k字(试图掩盖很多都是PPT上的事实)。
本文作者:Snowflake_Pink
本文链接:https://snowflake.pink/archives/8/
最后修改时间:2020-04-13 11:09:03
本站未注明转载的文章均为原创,并采用 CC BY-NC-SA 4.0 授权协议,转载请注明来源,谢谢!