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;
}
posted @ 2022-10-03 21:42  sandom  阅读(52)  评论(0)    收藏  举报