多比特杯武汉工程大学第六届ACM新生赛(同步赛)

这次比赛只拿下五题,本来有机会七题的,看错题加上调试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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_43983809

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值