D - Edge Split 生成树,环,P4889 kls与flag,P6154 游走

70 阅读2分钟

D - Edge Split 生成树,环

 先任意构造一个生成树,全是红边的,然后剩下的边都是蓝色,如果蓝色的边没有生成环的话就直接输出,不然就找出任意一条蓝色的边染成红色然后将一个端点u所连的红边除了刚才的那条边别的都变成蓝色,这样就保证蓝色和红色都没有环了,没有环每条边都会减少一个连通块,将会使得连通块总数最小

Codeforces Round #819 (Div. 1 + Div. 2) and Grimoire of Code Annual Contest 2022 A - D - 知乎 (zhihu.com)

ll t,n,m,s[200020],ans[200020];
struct node{
    ll l,r,id;
}e[200005];
vector<node>R,B;
set<ll>st;
ll findd(ll x){return x==s[x]?x:s[x]=findd(s[x]);}
int main(){
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n+10;i++) s[i]=i,ans[i]=0;
        R.clear();
        B.clear();
        st.clear();
        for(int i=1;i<=m;i++){
            ll u,vv;
            scanf("%lld%lld",&u,&vv);
            ll x=findd(u),y=findd(vv);
            if(x!=y){
                s[x]=y;
                R.push_back(node{u,vv,i});
                ans[i]=1;
            }
            else{
                st.insert(u);
                st.insert(vv);
                B.push_back(node{u,vv,i});
            }
        }
        if(m==n+2&&st.size()==3){
            node u=B.back();
            ans[u.id]=1;
            for(auto e:R){
                if(e.l==u.l||e.r==u.l) ans[e.id]=0;
            }
        }
        for(int i=1;i<=m;i++) printf("%lld",ans[i]);
        printf("\n");
    }
    return 0;
}

P4889 kls与flag - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 

计算出每个竹子向左或向右倒的点,用map记录每个点的次数,如果该点出现次数大于1,那么ans+=该点的次数,每次是先判断再map++

ll lcm(ll a,ll b){
    return a*b/__gcd(a,b);
}
ll fac[200005];
map<ll,ll>mp;
ll n,m,a[200005];
int main(){
    scanf("%lld%lld",&n,&m);
    ll ans=0;
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        if(mp[i-a[i]]>0) ans+=mp[i-a[i]];mp[i-a[i]]++;
        if(mp[i+a[i]]>0) ans+=mp[i+a[i]];mp[i+a[i]]++;
    }
    printf("%lld\n",ans);
    return 0;
}

P6154 游走 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 概率

期望等于总的路径的距离除以总的路径条数,f[i]为从i点出发的路径总距离,g[i]为从i点出发的路径总条数,则f[i]=sum(f[j]+g[j]),i指向j,加g[j]是因为所有距离都从f[j]的基础上加了1,g[i]=1+sum(g[j]),加1是因为终点和起点都可以是自己

T2-游走 - gyh20 的博客 - 洛谷博客

ll n,m,f[100005],g[100005];
ll head[700005],cnt;
struct node{
    ll next,to;
}edge[700005];
void addedge(ll from,ll to){
    edge[++cnt].to=to;
    edge[cnt].next=head[from];
    head[from]=cnt;
}
void dfs(ll u){
    if(g[u]) return;
    g[u]=1;
    for(int i=head[u];i;i=edge[i].next){
        ll j=edge[i].to;
        dfs(j);
        g[u]=(g[u]+g[j])%mod;
        f[u]=(f[u]+f[j]+g[j])%mod;
    }
}
int main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++) f[i]=g[i]=0;
    for(int i=1;i<=m;i++){
        ll u,vv;
        scanf("%lld%lld",&u,&vv);
        addedge(u,vv);
    }
    for(int i=1;i<=n;i++) if(!g[i]) dfs(i);
    ll z=0,m=0;
    for(int i=1;i<=n;i++){
        z=(z+f[i])%mod;
        m=(m+g[i])%mod;
    }
    ll ans=z*getinv(m)%mod;
    printf("%lld\n",ans);
    return 0;
}