zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 46 (Rated for Div. 2)E. We Need More Bosses

    题目链接:E. We Need More Bosses

    题解:tarjan有向图缩点之后求树的直径就是答案:应为在同一个强联通里的边就不是必须边,参考了这个

    #include<bits/stdc++.h>
    #include<set>
    #include<cstdio>
    #include<iomanip>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #define pb push_back
    #define mk make_pair
    #define ll long long
    #define fi first
    #define se second
    #define PI 3.14159265
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define eps 1e-7
    #define pii pair<int,int>
    #define pll pair<ll,ll>
    typedef unsigned long long ull;
    const int mod=998244353;
    const ll inf=0x3f3f3f3f3f3f3f;
    const int maxn=1e6+5;
    using namespace std;
    int n,m;
    vector<int>g[maxn],G[maxn];
    int dnf[maxn],low[maxn],ind,scc[maxn],scc_cnt,s[maxn],head,d[maxn];
    void tarjan(int v,int f)
    {
        dnf[v]=low[v]=++ind;
        s[++head]=v;
        for(int to :g[v])
        {
            if(f==to)continue;
            if(!dnf[to])
            {
                tarjan(to,v);
                low[v]=min(low[v],low[to]);
            }
            else low[v]=min(low[v],dnf[to]);
        }
        if(low[v]==dnf[v])
        {
            scc[v]=++scc_cnt;
            while(s[head]!=v)scc[s[head--]]=scc_cnt;
            head--;
        }
    }
    void dfs(int v,int f,int dep)
    {
        d[v]=dep;
        for(int to:G[v])
        {
            if(to!=f)dfs(to,v,dep+1);
        }
    }
    int main()
    {
        /* ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);*/
        //cin>>n>>m;
        scanf("%d %d",&n,&m);
        //cout<<d[(int)1e9]<<endl;
        for(int i=0;i<m;i++)
        {
            int x,y;
            //cin>>x>>y;
            scanf("%d %d",&x,&y);
            g[x].pb(y);g[y].pb(x);
        }
        tarjan(1,0); //cout<<"SSS"<<endl;
        for(int i=1;i<=n;i++)
        {
            for(int to:g[i])
            {
                if(scc[i]!=scc[to])
                {
                    G[scc[i]].pb(scc[to]);
                }
            }
        }
        dfs(1,0,0);
        int tmp=0,s;
        for(int i=1;i<=scc_cnt;i++)
        {
            if(d[i]>tmp)s=i,tmp=d[i];
        }
        for(int i=0;i<=scc_cnt;i++)d[i]=0;
        dfs(s,0,0);
        int ans=0;
        for(int i=1;i<=scc_cnt;i++)
        {
            ans=max(d[i],ans);
        }
        printf("%d
    ",ans);
        return 0;
    }

    有个相似的题

    题目链接:E. Anton and Tree

    题意:就是一次操作选中一个点并把所有到这个点最短路经过是颜色相同的点颜色反转,问至少几次操作把所有的颜色变为相同的点

    题解:把相同颜色的相邻的点缩成一个点然后求树的直径,答案时(直径+1)/2

    #include<bits/stdc++.h>
    #include<set>
    #include<cstdio>
    #include<iomanip>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #define pb push_back
    #define mk make_pair
    #define ll long long
    #define fi first
    #define se second
    #define PI 3.14159265
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define eps 1e-7
    #define pii pair<int,int>
    #define pll pair<ll,ll>
    typedef unsigned long long ull;
    const int mod=998244353;
    const ll inf=0x3f3f3f3f3f3f3f;
    const int maxn=1e6+5;
    using namespace std;
    int n,m;
    vector<int>g[maxn],G[maxn];
    int c[maxn];
    int sc[maxn],cnt;
    int dis[maxn];
    bool vis[maxn];
    void dfs(int v,int f,int ind,int cm)
    {
        sc[v]=ind;
        vis[v]=true;
        for(int to:g[v])
        {
            if(to==f)continue;
            if(!vis[to]&&c[to]==cm)dfs(to,v,ind,cm);
        }
    }
    void dfs1(int v,int f,int d)
    {
        dis[v]=d;
        for(int to:G[v])
        {
            if(to==f)continue;
                dfs1(to,v,d+1);
        }
    }
    int main()
    {
         ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        cin>>n;
        for(int i=1;i<=n;i++)cin>>c[i];
        for(int i=0;i<n-1;i++)
        {
            int x,y;
            cin>>x>>y;
            g[x].pb(y);g[y].pb(x);
        }
        for(int i=1;i<=n;i++)
        {
            if(!vis[i]) dfs(i,0,++cnt,c[i]);
        }
        for(int i=1;i<=n;i++)
        {
            for(int to:g[i])
            {
                if(sc[to]!=sc[i])
                {
                    G[sc[i]].pb(sc[to]);
                }
            }
        }
        dfs1(1,0,0);int tmp=0,s;
        for(int i=1;i<=cnt;i++)
        {
            if(dis[i]>tmp)s=i,tmp=dis[i];
        }
        memset(dis,0,sizeof(dis));
        dfs1(s,0,0);
        int ans=0;
        for(int i=1;i<=cnt;i++)
        {
            ans=max(ans,dis[i]);
        }
        cout<<(ans+1)/2<<endl;
        return 0;
    }
    

      

  • 相关阅读:
    Beyond Compare比较图片怎么修改背景颜色
    Leonardo's Notebook UVALive
    Saddle Point ZOJ
    概率dp总结 正在更新
    First Knight UVALive
    Scout YYF I POJ
    RedIsGood TopCoder
    聪聪和可可 HYSBZ
    So you want to be a 2n-aire? UVA
    国家队论文集
  • 原文地址:https://www.cnblogs.com/lhclqslove/p/9295804.html
Copyright © 2011-2022 走看看