CSP-S模拟16
今天的改题异常的轻松。两道水题,两个科技。
T1.猜道路
签到题。So show the code on right.
代码
#define sandom signed
#define fre(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#include <bits/stdc++.h>
#define re register int
#define int long long
using namespace std;
const int Z = 320;
inline int read() { int x = 0, f = 0; char c = getchar(); while (!isdigit(c)) f |= c == '-', c = getchar(); while (isdigit(c)) x = (x << 1) + (x << 3) + (c ^ 48), c = getchar(); return f ? -x : x; }
int n, m, ans;
int dis[Z][Z], a[Z][Z];
bool solve()
{
for (re i = 1; i <= n; i++)
for (re j = 1; j <= n; j++)
for (re k = 1; k <= n; k++)
if (i != j && k != i && k != j)
{
if (dis[i][k] + dis[k][j] < dis[i][j]) return false;//给出的并不是最短路
if (dis[i][k] + dis[k][j] == dis[i][j]) a[i][j] = 0;//这条路可以由其他的拼接而成
}
return true;
}
sandom main()
{
n = read();
for (re i = 1; i <= n; i++)
for (re j = 1; j <= n; j++)
dis[i][j] = read(), a[i][j] = 1;
if (solve())
{
for (re i = 1; i <= n; i++)
for (re j = 1; j <= n; j++)
ans += dis[i][j] * a[i][j];
cout << ans / 2;//无向边
}
else puts("-1");
return 0;
}
T2.简单环
我只打了个暴力……但这好像是\(tarjan\)板子。把所有点双联通分量找出来,如果点数等于边数,那么是简单环,因为数据水,所以暴力判断即可。
代码
#define sandom signed
#define fre(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#include <bits/stdc++.h>
#define re register int
using namespace std; int wrt[20], TP;
const int Z = 1e5 + 10;
inline int read() { int x = 0, f = 0; char c = getchar(); while (!isdigit(c)) f |= c == '-', c = getchar(); while (isdigit(c)) x = (x << 1) + (x << 3) + (c ^ 48), c = getchar(); return f ? -x : x; }
inline void write(int x) { TP = 0; if (x < 0) putchar('-'), x = -x; while (x >= 10) wrt[++TP] = x % 10, x /= 10; wrt[++TP] = x; while (TP) putchar(wrt[TP--] | 48); putchar(' '); }
int n, m;
vector <int> ans;
struct edge { int u, v, ne; } e[Z << 1];
int head[Z], cnt;
inline void add(int x, int y, int id) { e[id] = edge{x, y, head[x]}; head[x] = id; }
int dfn[Z], low[Z], tim, dfs[Z], top;
vector <int> vdcc[Z];
int be[Z], tot[Z], num;
void tarjan(int rt)
{
dfn[rt] = low[rt] = ++tim;
dfs[++top] = rt;
for (re i = head[rt]; i; i = e[i].ne)
{
int son = e[i].v;
if (!dfn[son])
{
tarjan(son);
low[rt] = min(low[rt], low[son]);
if (low[son] >= dfn[rt])
{
int j; num++;
vdcc[num].push_back(rt);
do
{
j = dfs[top--];
vdcc[num].push_back(j);
} while (j != son);
}
}
else low[rt] = min(low[rt], dfn[son]);
}
}
void calc(int t)
{
for (auto rt : vdcc[t]) be[rt] = t;
for (auto rt : vdcc[t])
for (re i = head[rt]; i; i = e[i].ne)
if (be[e[i].v] == t) tot[t]++;
tot[t] >>= 1;
}
void solve(int t)
{
for (auto rt : vdcc[t]) be[rt] = t;
for (auto rt : vdcc[t])
for (re i = head[rt]; i; i = e[i].ne)
if (be[e[i].v] == t && i <= m) ans.push_back(i);
}
sandom main()
{
n = read(), m = read();
for (re i = 1; i <= m; i++)
{
int u = read(), v = read();
add(u, v, i), add(v, u, i + m);
}
for (re i = 1; i <= n; i++) if (!dfn[i]) tarjan(i);
for (re i = 1; i <= num; i++) calc(i);//计算每个联通分量的边数
for (re i = 1; i <= num; i++)
if (vdcc[i].size() == tot[i]) solve(i);//点数=边数,简单环
sort(ans.begin(), ans.end());
write(ans.size()), putchar('\n');
for (auto i : ans) write(i);
return 0;
}
T3.汉明距离
我\(bitset\)因为内存,还没暴力快?但这个题是\(FFT\),开科技那就算了罢。
代码
#define sandom signed
#define fre(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#include <bits/stdc++.h>
#define re register int
using namespace std;
const int Z = 1e6 + 10;
inline int min(int a, int b) { return a < b ? a : b; }
int n, m, ans = 1e9;
string a, b;
bitset <Z> A, B;
sandom main()
{
cin >> a >> b;
n = a.length(), m = b.length();
for (re i = 0; i < m; i++) B[i] = b[i] - '0', A[i] = a[i] - '0';
for (re i = 0; i <= n - m; i++)
{
ans = min(ans, (A ^ B).count());
A >>= 1;
A[m - 1] = a[i + m] - '0';
}
cout << ans;
return 0;
}
T4.勇者的后缀
我tm因为字典序挂了,没有暴力分……题意很明确的告诉了这是个\(SA\),后缀数组,改题压力--。
代码
#define sandom signed
#define fre(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#include <bits/stdc++.h>
#define re register int
using namespace std; int wrt[20], TP;
const int Z = 2e5 + 10; typedef pair<int, int> paint;
inline int read() { int x = 0, f = 0; char c = getchar(); while (!isdigit(c)) f |= c == '-', c = getchar(); while (isdigit(c)) x = (x << 1) + (x << 3) + (c ^ 48), c = getchar(); return f ? -x : x; }
inline void write(int x) { TP = 0; if (x < 0) putchar('-'), x = -x; while (x >= 10) wrt[++TP] = x % 10, x /= 10; wrt[++TP] = x; while (TP) putchar(wrt[TP--] | 48); putchar(' '); }
inline int max(int a, int b) { return a > b ? a : b; } inline int min(int a, int b) { return a < b ? a : b; }
int n, m, ans, pos;
char nm[Z];
inline bool cmp(int i)
{
int j = 0;
while (nm[pos + j] == nm[i + j]) j++;
return nm[pos + j] > nm[i + j];
}
sandom main()
{
scanf("%s", nm + 1); n = strlen(nm + 1);
m = read();
while (m--)
{
int k = read(), l = read(), r = read(); ans = -1;
for (re i = l; i <= r; i++)
{
int j = 0;
while (i + j <= n && k + j <= n && nm[k + j] == nm[i + j]) j++;
if (ans < j) ans = j, pos = i;
else if (ans == j) if (cmp(i)) pos = i;
}
write(ans), write(pos), putchar('\n');
}
return 0;
}

浙公网安备 33010602011771号