牛客练习赛43

A

#include <bits/stdc++.h>
using namespace std;
const int maxn = 105;
pair<int, int> arr[maxn];
map<int, int> mp;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    bool flg = false;
    for(int i = 0; i < n; ++i) {
        int a, b;
        cin >> a >> b;
        arr[i].first = a, arr[i].second = b;
        if(mp.find(a + b) != mp.end()) {
            int id = mp[a + b];
            if(arr[id].first + arr[id].second == a) flg = true;
        }
        mp[a] = i;
    }
    if(flg) cout << "YE5" << endl;
    else cout << "N0" << endl;
}

B
输出小数后k1到k2位,因为k2过大,不能暴力
但是k2-k1<=1e5,我们处理出第k1位然后暴力即可,快速幂(a%m)*10

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll m, n;
ll qpow(ll b) {
    ll res = m, a = 10 % n;
    while(b) {
        if(b & 1) res = res * a % n;
        b >>= 1;
        a = a * a % n;
    }
    return res;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--) {
        int k1, k2;
        scanf("%lld%lld%d%d", &m, &n, &k1, &k2);
        if(n == m) {
            for(int i = k1; i <= k2; ++i) printf("0");
            printf("\n");
        }
        else {
            if(k1 == 1) {
                ll tmp = m;
                for(int i = k1; i <= k2; ++i) {
                    printf("%lld", tmp * 10 / n);
                    tmp = (tmp * 10) % n;
                }
                printf("\n");
            }
            else {
                ll tmp = qpow(k1 - 1);
                for(int i = k1; i <= k2; ++i) {
                    printf("%lld", tmp * 10 / n);
                    tmp = (tmp * 10) % n;
                }
                printf("\n");
            }
        }
    }
}

C
最小生成树
注意卡常优化:结合并查集的路径压缩与启发式合并https://blog.csdn.net/qq_27121257/article/details/77185604

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline void read(int &x){
    int data = 0, w = 1;
    char ch = getchar();
    while(ch != '-' && !isdigit(ch))
        ch = getchar();
    if(ch == '-')
        w = -1, ch = getchar();
    while(isdigit(ch))
        data = 10 * data + ch - '0', ch = getchar();
    x = data * w;
}
inline void readll(ll &x){
    ll data = 0;
    int w = 1;
    char ch = getchar();
    while(ch != '-' && !isdigit(ch))
        ch = getchar();
    if(ch == '-')
        w = -1, ch = getchar();
    while(isdigit(ch))
        data = 10 * data + ch - '0', ch = getchar();
    x = data * w;
}
const int maxn = 1e6 + 5;
int T[maxn], fa[maxn];
int find(int x) {
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void merge(int a, int b) {
    fa[find(a)] = find(b);
}
struct node {
    int u, v;
    ll c;
    bool operator <(const node& x) const {
        return c > x.c;
    }
};
priority_queue<node> Q;
int vis[maxn];
vector<pair<int, int>>E[maxn];
int main()
{
    int n, m, k;
    ll t;
    read(n), read(m), read(k), readll(t);
    for(int i = 1; i <= n + 1; ++i) fa[i] = i;
    for(int i = 2; i <= n + 1; ++i) {
        read(T[i]);
        Q.push((node){1, i, T[i]});
    }
    for(int i = 0; i < k; ++i) {
        int x;
        read(x);
        Q.push((node){1, x + 1, 0});
    }
    for(int i = 0; i < m; ++i) {
        int u, v, c;
        read(u), read(v), read(c);
        E[u + 1].push_back(make_pair(v + 1, c));
        E[v + 1].push_back(make_pair(u + 1, c));
    }
    ll ans = 0;
    while(!Q.empty()) {
        node top = Q.top();
        Q.pop();
        int u = top.u, v = top.v;
        if(find(u) == find(v)) continue;
        merge(u, v);
        ans += top.c;
        if(!vis[u]) {
            for(int i = 0; i < E[u].size(); ++i) {
                if(!vis[E[u][i].first]) Q.push((node){u, E[u][i].first, E[u][i].second});
            }
            vis[u] = 1;
        }
        if(!vis[v]) {
            for(int i = 0; i < E[v].size(); ++i) {
                if(!vis[E[v][i].first]) Q.push((node){v, E[v][i].first, E[v][i].second});
            }
            vis[v] = 1;
        }
    }
    if(ans <= t) puts("Yes");
    else puts("No");
}

D
网络流
根据题意将每个点分为i和i’,建立源点到每个点i的容量为vi的边,建立i’到汇点的容量为wi的边;需要输出所有边中的最大边:二分+floyd处理即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 5;
const int maxm = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const ll INF = 10000000000000;
struct Edge {
    int from, to, cap, flow;
    Edge() {}
    Edge(int f, int t, int c, int fl) {
        from = f, to = t, cap = c, flow = fl;
    }
};
struct Dinic{
    int n, m, s, t;
    vector<Edge> edges;
    vector<int> g[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];
    void init(int n){
        this->n = n;
        for(int i = 0; i < n; i++) g[i].clear();
        edges.clear();
    }
    void AddEdge(int from, int to, int cap){
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, 0, 0));//反向弧
        m = edges.size();
        g[from].push_back(m - 2);
        g[to].push_back(m - 1);
    }
    bool Bfs(){
        memset(vis, 0, sizeof(vis));
        queue<int> q;
        q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while(!q.empty()){
            int x = q.front(); q.pop();
            for(int i = 0; i < (int)g[x].size(); i++){
                Edge &e = edges[g[x][i]];
                if(!vis[e.to] && e.cap > e.flow){
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int Dfs(int x, int a){
        if(x == t || a == 0) return a;
        int flow = 0, f;
        for(int& i = cur[x]; i < (int)g[x].size(); i++){
            Edge &e = edges[g[x][i]];
            if(d[x] + 1 == d[e.to] && (f = Dfs(e.to, min(a, e.cap - e.flow))) > 0){
                e.flow += f;
                edges[g[x][i]^1].flow -= f;
                flow += f;
                a -= f;
                if(a == 0) break;
            }
        }
        return flow;
    }
    int Maxflow(int s, int t){
        this->s = s; this->t = t;
        int flow = 0;
        while(Bfs()){
            memset(cur, 0, sizeof(cur));
            flow += Dfs(s, inf);
        }
        return flow;
    }
} dc;
int vi[maxn], wi[maxn];
ll dis[maxn][maxn];
set<ll> mp;
ll arr[maxm];
int n, m, sum;
bool check(ll x) {
    dc.init(n + n + 2);
    for(int i = 1; i <= n; ++i) {
        dc.AddEdge(0, i, vi[i]);
        dc.AddEdge(n + i, n + n + 1, wi[i]);
    }
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
            if(dis[i][j] <= x) dc.AddEdge(i, n + j, sum);
    if(dc.Maxflow(0, n + n + 1) == sum) return true;
    else return false;
}
int main()
{
    sum = 0;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
            dis[i][j] = INF;
    for(int i = 1; i <= n; ++i) {
        scanf("%d%d", &vi[i], &wi[i]);
        sum += vi[i];
    }
    for(int i = 0; i < m; ++i) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        if(u != v) dis[u][v] = dis[v][u] = min(dis[u][v], w * 1ll);
    }
    for(int i = 1; i <= n; ++i) dis[i][i] = 0;
    for(int k = 1; k <= n; ++k) {
        for(int i = 1; i <= n; ++i) {
            for(int j = 1; j <= n; ++j) {
                dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
            }
        }
    }
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= n; ++j) {
            if(dis[i][j] != INF) mp.insert(dis[i][j]);
        }
    }
    int tot = 0;
    for(set<ll>::iterator it = mp.begin(); it != mp.end(); ++it) {
        arr[tot++] = *it;
    }
    bool flg = false;
    int l = 0, r = tot;
    while(l < r) {
        int mid = l + r >> 1;
        if(check(arr[mid])) flg = true, r = mid;
        else l = mid + 1;
    }
    printf("%lld\n", flg ? arr[l] : -1);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值