赞
踩
整理的算法模板合集: ACM模板
实际上是一个全新的
精炼模板整合计划
比赛链接:https://codeforces.com/gym/102992
Problem
对于给定的 n × m n \times m n×m 的方格, 0 0 0 代表障碍, 1 1 1 代表袋鼠。有一串随机生成的长为 5 × 1 0 4 5 \times 10^4 5×104的指令,仅包含 LRUD \text{LRUD} LRUD 字符,分别表示将所有袋鼠同时向某个方向移动(若能移动,即不经过障碍、不超出方格范围)。现要求构造一个 n × m n \times m n×m 方格图,使得对于随机生成的 500 500 500 串指令,至少有 125 125 125 个满足执行后,所有袋鼠不都在同一个方格。要求构造的袋鼠方格连通、且不含环。
1 ≤ n , m ≤ 20 1 \le n, m \le 20 1≤n,m≤20。
Solution
我们只需要执行 1 4 \cfrac{1}{4} 41 的指令执行即可,也就是每只袋鼠至少有一个方向是墙,所以我们可以构造一个不对称的路径,以及一些分岔路口,例如一些 Z 字形路径。注意袋鼠们必须连通以及不能有环。
#include<bits/stdc++.h> using namespace std; int main(){ char ans[21][21] = { "20 20", "11011111011111011111", "10110100110100110100", "11101101101101101101", "10011011011011011001", "10110110110110110111", "01101101101101101101", "11011011011011011011", "10110110110110110110", "11101101101101101101", "10011011011011011001", "10110110110110110111", "01101101101101101101", "11011011011011011011", "10110110110110110110", "11101101101101101101", "10011011011011011001", "10110110110110110111", "01101101101101101101", "01011001011001011001", "11110111110111110111", }; for(int i = 0; i <= 20; ++i){ cout << ans[i] << endl; } return 0; }
Problem
给出一个无向图,寻找它的一棵生成树,要求生成树上每个点的度数都要小于等于 n 2 \cfrac{n}{2} 2n 。
Solution
首先随便找到一棵生成树,寻找它度数最大的点,在所有节点中,度数大于 n 2 \cfrac{n}{2} 2n 的节点最多只有一个,若找不到直接输出,找到了则令其为根节点,对所有不在生成树上的边进行枚举,若这条边的起点终点在树上的lca是根节点,则说明这条边的加入可以令根节点度数-1,但是在两个点都是根节点的儿子节点的情况下,会令选择的另一边的节点度数+1,所以在删边加边的过程中要判断是否会导致其他节点度数大于 n 2 \cfrac{n}{2} 2n。
动态加边删边求lca实在是不会…但是还好可以用并查集来做,首先将根节点的所有子树各自构成集合,集合祖先为根节点的儿子节点,每次遍历边查询两端点是否在同一集合即可。
Code
#include <bits/stdc++.h> #define reg register #define ios ios::sync_with_stdio(false) using namespace std; typedef long long ll; typedef pair<int,int> pii; const int inf = 0x3f3f3f3f; const double eps = 1e-10; const int maxn = 2e5 + 10; const double pi = acos(-1.0); const ll mod = 1e9 + 7; vector<pair<int,int>> es; map<pair<int,int>,int> mp; struct Edge{ int to,nxt; }edges[maxn << 2]; int head[maxn], idx; int deg[maxn]; void add(int u,int v) { edges[idx] = { v,head[u]}, head[u] = idx++; edges[idx] = { u,head[v]}, head[v] = idx++; } int pre[maxn]; int chose[maxn]; int fi(int x) { return x == pre[x] ? x : pre[x] = fi(pre[x]);} void dfs(int u,int fa, int sig) { pre[u] = sig; for(int i = head[u];~i;i = edges[i].nxt){ int v = edges[i].to; if(v == fa) continue; dfs(v,u,sig); } } void init(int n,int m) { mp.clear(); es.clear(); for(int i = 0;i <= n;++i){ head[i] = -1; deg[i] = 0; pre[i] = i; } for(int i = 0;i <= m;++i){ chose[i] = 0; } idx = 0; } int main() { int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d %d",&n,&m); init(n,m); for(int i = 0;i < m;++i){ int u,v; scanf("%d%d",&u,&v); if(u > v) swap(u,v); es.push_back({ u,v}); } sort(es.begin(),es.end()); es.erase(unique(es.begin(),es.end()),es.end()); m = static_cast<int>(es.size()); // 删除重边自环 for(int i = 0;i < m;++i){ int u = es[i].first; int v = es[i].second; mp[{ u,v}] = mp[{ v,u}] = i; int fu = fi(u),fv = fi(v); if(fu != fv){ add(u,v); //kruskal 建生成树 pre[fu] = fv; deg[u]++; deg[v]++; chose[i] = 1; } } int flag = 0; for(int i = 2;i <= n;++i){ if(fi(i) != fi(1)) flag = 1; } if(flag) { puts("No"); continue; } int rt = -1; for(int i = 1;i <= n;++i){ if(deg[i] > n/2){ rt = i; break; } } if(rt == -1){ puts("Yes"); for(int i = 0;i < m;++i){ if(chose[i]){ printf("%d %d\n",es[i].first,es[i].second); } } continue; } for(int i = 1;i <= n;++i) pre[i] = i; for(int i = head[rt];~i;i = edges[i].nxt){ dfs(edges[i].to,rt,edges[i].to); } for(int i = 0;i < m;++i){ if(chose[i]) continue; int u = es[i].first, v = es[i].second; int fu = fi(u), fv = fi(v); if(fu == fv || u == rt || v == rt) continue; deg[rt]--; deg[u]++; deg[v]++; deg[fu]--; if(deg[u] > n/2 || deg[v] > n/2){ //检测是否可行,不可行就恢复 deg[fu]++; deg[fv]--; if(deg[u] > n/2 || deg[v] > n/2){ deg[rt]++; deg[u]--; deg[v]--; deg[fv]++; continue; } else{ pre[fv] = fu; chose[i] = 1; chose[mp[{ rt,fv}]] = 0; } } else{ pre[fu] = fv; chose[i] = 1; chose[mp[{ rt,fu}]] = 0; } if(deg[rt] <= n/2) break; } if(deg[rt] <= n/2){ puts("Yes"); for(int i = 0;i < m;++i){ if(chose[i]){ printf("%d %d\n",es[i].first,es[i].second); } } } else puts("No"); } return 0; }
Problem
在一个直角坐标系中,给定起点 ( 0 , 0 ) (0, 0) (0,0),一个障碍 ( m x , m y ) (m_x, m_y) (mx,my) 以及一串长度为 n n n 的指令,仅包含 L / R / U / D \text{L / R / U / D} L / R / U / D 字符,分别表示向左右上下移动,请你调整指令顺序让移动过程不经过 ( m x , m y ) (m_x, m_y) (mx,my),有解输出指令字符,无解输出 impossible \text{impossible} impossible 。
1 ≤ n ≤ 1 0 5 , − 1 0 9 ≤ m x , m y ≤ 1 0 9 , ∑ n i ≤ 1 0 6 1\le n \le 10^5, -10^9 \le m_x, m_y \le 10^9, \sum n_i \le 10^6 1≤n≤105,−109≤m
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。