SDUT 2023 summer team contest(for 22) - 14 ADEGHK

ADEGHK

A - Amanda Lounges

在这里插入图片描述
染色+dfs
分类 将 c = 2 c=2 c=2的两边机场染色为 1 1 1 c = 0 c=0 c=0的两边机场染色为 − 1 -1 1
对于上面两种情况,染色时如果出现矛盾情况,就直接“impossible”
c = 1 c=1 c=1的两边机场建图连起来染色为0
这样就能把所有的机场分为两部分
一部分是color不为0的机场以及它相连的机场 另一部分是剩下的color全是0的机场
对两个部分进行dfs遍历染色 :
第一部分都是因为 c = 1 c=1 c=1被连起来的,因此两边服务区情况应该不相同,一边是 − 1 -1 1另一边一定是 1 1 1
第二部分全都是因为 c = 1 c=1 c=1连接起来的,我们可以假设一个点是1或者-1,对剩下的所有点遍历两边,求出所需要建立服务区的最小值(因为要么建服务区,要么不建,是相对的,所以染色成-1和染色成1最终形成的-1和1的数量一定是相对的,知道一个就知道另一个情况的,所以直接取ab最小值即可)

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'

#define int long long
#define xx first
#define yy second
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;

void ClearFloat()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
}
int read()
{
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}

int v[N], n, m, x, t, T;
int e[N], ne[N], h[N], idx;
int color[N], flag, a, b, res;
bool st[N];
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int dfs(int u, int c, int k)
{
    if (k)
    {
        if (color[u] == 1)
            b++;
        else
            a++;
    }
    else
    {
        if (color[u] == 1)
            res++;
    }
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (color[j] == c)
            return 0;
        if (!st[j])
        {
            st[j] = 1;
            if (color[j] == 0)
                color[j] -= c;
            if (!dfs(j, color[j], k))
                return 0;
        }
    }
    return 1;
}
signed main()
{
    ClearFloat();
    memset(h, -1, sizeof h);
    flag = 1;
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        if (c == 0)
        {
            if (color[a] == 1 || color[b] == 1)
                flag = 0;
            color[a] = color[b] = -1;
        }
        else if (c == 2)
        {
            if (color[a] == -1 || color[b] == -1)
                flag = 0;
            color[a] = color[b] = 1;
        }
        else
            add(a, b), add(b, a);
    }
    // 操作c = 0和c = 2需要修建多少服务区并判断与c = 1相连的情况是否合法;
    for (int i = 1; i <= n; i++)
    {
        if (!st[i] && color[i])
        {
            st[i] = 1;
            if (!dfs(i, color[i], 0))
                flag = 0;
        }
    }
    // 给(c = 1 && st[i] == 0)的情况染色;
    for (int i = 1; i <= n; i++)
    {
        if (st[i] == 1)
            continue;
        a = 0, b = 0, st[i] = 1, color[i] = 1;
        if (dfs(i, 1, 1) == 0)
            flag = 0;
        res += min(a, b);
    }
    if (flag)
        cout << res << endl;
    else
        cout << "impossible";
    return 0;
}


D - Dice Game

在这里插入图片描述
直接求一下两个人的数字之和。因为求概率的时候都会约分掉

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'

#define int long long
#define xx first
#define yy second
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;

void ClearFloat()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
}
int read()
{
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}

int v[N], n, m, k, x, t, T;

signed main()
{
    double sum1, sum2, a1, b1, a2, b2;
    cin >> a1 >> b1 >> a2 >> b2;
    sum1 = b1 + a1 + b2 + a2;
    cin >> a1 >> b1 >> a2 >> b2;
    sum2 = b1 + a1 + b2 + a2;
    // cout << sum1 << " " << sum2 << endl;
    if (sum1 == sum2)
        cout << "Tie";
    if (sum1 > sum2)
        cout << "Gunnar";
    if (sum2 > sum1)
        cout << "Emma";
    return 0;
}

E - Opening Ceremony

在这里插入图片描述
思维题 脑子转不过来的话可以写的麻烦一些

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;

int n, m, k, a[N];

signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    sort(a + 1, a + n + 1);
    int mi = 0;
    for (int i = 1; i <= n; i++)
        mi = min(mi + 1, a[i]);
    cout << mi << "\n";
}

G - Outing

在这里插入图片描述
tarjan缩点+背包
不会tarjan缩点的可以看一下这篇文章讲的很详细

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'

#define int long long
#define xx first
#define yy second
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;

void ClearFloat()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
}
int read()
{
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}

int v[N], n, m, k, t, T;
vector<int> g[N];
int dfn[N], low[N], id[N], sz[N], cnt;
int stk[N], top, f[N], p[N];
bool in[N];
map<int, PII> mp;
void tarjan(int u)
{
    dfn[u] = low[u] = ++k;
    stk[++top] = u;
    in[u] = 1;
    for (auto j : g[u])
    {
        if (!dfn[j])
        {
            tarjan(j);
            low[u] = min(low[u], low[j]);
        }
        else if (in[j])
            low[u] = min(low[u], low[j]);
    }
    if (dfn[u] == low[u])
    {
        int y;
        ++cnt;
        do
        {
            y = stk[top--];
            in[y] = 0;
            id[y] = cnt;
            sz[cnt]++;
        } while (y != u);
    }
}
int find(int x)
{
    if (x != p[x])
        p[x] = find(p[x]);
    return p[x];
}
signed main()
{
    ClearFloat();
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        cin >> v[i];
        g[i].push_back(v[i]);
    }
    for (int i = 1; i <= n; i++)
    {
        if (!dfn[i])
            tarjan(i);
    }
    for (int i = 1; i <= n; i++)
        p[i] = i;
    for (int i = 1; i <= n; i++)
    {
        int x = id[i], y = id[v[i]];
        if (find(x) != find(y))
            p[find(x)] = p[find(y)];
    }
    for (int i = 1; i <= cnt; i++)
    {
        mp[find(i)].xx = max(mp[find(i)].xx, sz[i]);
        mp[find(i)].yy += sz[i];
    }
    for (auto t : mp)
    {
        for (int i = m; i >= 0; i--)
        {
            for (int j = t.yy.xx; j <= t.yy.yy; j++)
                if (i >= j)
                    f[i] = max(f[i], f[i - j] + j);
        }
    }
    cout << f[m];
    return 0;
}


H - Clock Pictures

在这里插入图片描述
KMP+倍增
谁能想到这是KMP啊
先sort以下 再把所有相邻的指针求一下间距,给其中一个倍增一倍,然后KMP找字串,能找到就可能是有相同时间
不会KMP的可以看一下这篇文章

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'

#define int long long
#define xx first
#define yy second
typedef pair<int, int> PII;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;

void ClearFloat()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
}
int read()
{
    int s = 0, w = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        s = s * 10 + ch - '0', ch = getchar();
    return s * w;
}

int v[N], f[N], n, m, k, x, t, T;
int nt[N];

void getnext()
{
    int j, k;
    j = 0, k = -1;
    nt[0] = -1;
    while (j < n)
    {
        if (k == -1 || f[j] == f[k])
        {
            j++, k++;
            nt[j] = k;
        }
        else
            k = nt[k];
    }
}
bool kmp()
{
    getnext();
    int i = 0, j = 0;
    while (i < 2 * n && j < n)
    {
        if (j == -1 || v[i] == f[j])
        {
            i++, j++;
        }
        else
            j = nt[j];
    }
    if (j >= n)
        return 1;
    else
        return 0;
}
signed main()
{
    ClearFloat();
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> v[i];
    for (int i = 1; i <= n; i++)
        cin >> f[i];
    sort(v + 1, v + 1 + n);
    sort(f + 1, f + 1 + n);
    v[0] = 360000 - v[n] + v[1], f[0] = 360000 - f[n] + f[1];
    for (int i = 1; i < n; i++)
        v[i] = v[i + 1] - v[i], f[i] = f[i + 1] - f[i];
    for (int i = 0; i < n; i++)
        v[i + n] = v[i];
    if (kmp())
        cout << "possible";
    else
        cout << "impossible";
    return 0;
}


K - Train Passengers

在这里插入图片描述
模拟一下即可

#include <bits/stdc++.h>

using namespace std;

long long c;
int n;
int main()
{
    long long num=0;
    cin>>c>>n;
    for(int i=1;i<=n;i++)
    {
        int le,in,wa;
        cin>>le>>in>>wa;
        if(i==1)
        {
            if(le!=0)
            {
                cout<<"impossible";
                return 0;
            }
        }
        if(i==n)
        {
            if(in!=0||wa!=0||num-le!=0)
            {
                cout<<"impossible";
                return 0;
            }
        }
        int sw=in-le;
        if(num+sw>c||num+sw<0)
        {
            cout<<"impossible";
            return 0;
        }
        else num+=sw;
        if(num!=c&&wa!=0)
        {
            cout<<"impossible";
            return 0;
        }
    }
    cout<<"possible";
    return 0;
}

∗ ∗ 下次一定 ∗ ∗ **下次一定** 下次一定
请添加图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值