牛客练习赛43

    xiaoxiao2022-07-07  198

    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)