这次比赛只拿下五题,本来有机会七题的,看错题加上调试bug浪费很多时间,记录下做的题
薇尔莉特能拿多少棵碧根果
tarjan缩点加上dfs
#include<iostream>
#include<queue>
#include<stack>
#include<cstring>
#include<set>
using namespace std;
const int N = 2e5+5;
int h[N];
int cnt=1;
int e[N], nx[N];
int w[N];
void add(int a,int b){
e[cnt] = b, nx[cnt] = h[a], h[a] =cnt++;
}
int point[N];
int p_cnt[N];
struct tj{
int h[N];
int cnt=1;
int e[N], nx[N];
void add(int a,int b){
e[cnt] = b, nx[cnt] = h[a], h[a] = cnt++;
}
int dfn[N], low[N];
int point_cnt = 0;
bool instack[N];
int n;
void init(int n1){
n = n1;
memset(h,0,sizeof h);
memset(e,0,sizeof e);
memset(nx,0,sizeof nx);
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(instack, 0, sizeof instack);
}
stack<int> s;
int tn=0;
void dfs(int u){
point_cnt++;
dfn[u] = low[u] = point_cnt;
s.push(u);
instack[u] =true;
for(int i=h[u];i;i=nx[i]){
int t=e[i];
if(!dfn[t]){
dfs(t);
low[u] = min(low[u], low[t]);
}else if(instack[t]){
low[u] = min(low[u], dfn[t]);
}
}
if(dfn[u]==low[u]){
int node;
tn++;
do{
node = s.top();
point[node] = tn;
p_cnt[tn]++;
instack[node] = 0;
s.pop();
}while(node!=u);
}
}
void solve(){
for(int i=1;i<=n;i++){
if(!dfn[i]){
dfs(i);
}
}
}
};
bool vis[N];
int MAX = 1e8;
int w1[N];
// int dp[N];
void dfs(int u){
vis[u] =true;
int tmp = 0;
for(int i=h[u];i;i=nx[i]){ //这里图的遍历老是写成h[i],shit,shit,shit................
int t = e[i];
if(!vis[t]){
dfs(t);
}
tmp = max(tmp, w1[t]);
}
w1[u] = min(MAX, tmp+w1[u]);
}
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>w[i];
}
tj t;
t.init(n);
vector<pair<int,int>> es;
set<pair<int,int>> ss;
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
t.add(a,b);
es.push_back({a,b});
}
t.solve();
for(auto&[a,b]:es){
if(point[a]!=point[b])
ss.insert({point[a], point[b]});
}
for(auto&[a,b]:ss){
add(a, b);
}
for(int i=1;i<=n;i++){
if(p_cnt[point[i]]>1){
w1[point[i]] = MAX;
}else{
w1[point[i]] = w[i];
}
}
int mx = 0;
for(int i=1;i<=t.tn;i++){
if(!vis[i]){
dfs(i);
mx = max(mx, w1[i]);
}
}
int res = 0;
for(int i=1;i<=n;i++){
if(w1[point[i]] == mx)res++;
}
cout<<res<<endl<<mx;
}
n n n\sqrt n nn的时间复杂度算法可以过,涨知识了,并查集,没啥好说的
#include<iostream>
#include<cstring>
#include<vector>
#include<set>
using namespace std;
const int N=1e5+5;
// int f[N];
int arr[N];
vector<int> dp[N];
int fa[N];
int get(int a){
return fa[a]==a?a:(fa[a] = get(fa[a]));
}
void merge(int i,int j){
int fi = get(i), fj = get(j);
if(fi!=fj){
fa[fi] = fj;
}
}
int main(){
int n;
cin>>n;
set<int> s;
for(int i=0;i<n;i++){
cin>>arr[i];
s.insert(arr[i]);
}
for(int x:s)fa[x] =x;
for(int x:s){
for(int j=1;j*j<=x;j++){
if(x%j==0 && s.count(j)){
merge(x, j);
}
if(x%j==0&&s.count(x/j)){
merge(x, x/j);
}
}
}
int ans=0;
for(int x:s){
ans += fa[x]==x;
}
cout<<ans;
}