zoukankan      html  css  js  c++  java
  • CodeForces

    Your friend is developing a computer game. He has already decided how the game world should look like — it should consist of nn locations connected by mtwo-way passages. The passages are designed in such a way that it should be possible to get from any location to any other location.

    Of course, some passages should be guarded by the monsters (if you just can go everywhere without any difficulties, then it's not fun, right?). Some crucial passages will be guarded by really fearsome monsters, requiring the hero to prepare for battle and designing his own tactics of defeating them (commonly these kinds of monsters are called bosses). And your friend wants you to help him place these bosses.

    The game will start in location ss and end in location tt, but these locations are not chosen yet. After choosing these locations, your friend will place a boss in each passage such that it is impossible to get from ss to tt without using this passage. Your friend wants to place as much bosses as possible (because more challenges means more fun, right?), so he asks you to help him determine the maximum possible number of bosses, considering that any location can be chosen as ss or as tt.

    Input

    The first line contains two integers nn and mm (2n31052≤n≤3⋅105, n1m3105n−1≤m≤3⋅105) — the number of locations and passages, respectively.

    Then mm lines follow, each containing two integers xx and yy (1x,yn1≤x,y≤n, xyx≠y) describing the endpoints of one of the passages.

    It is guaranteed that there is no pair of locations directly connected by two or more passages, and that any location is reachable from any other location.

    Output

    Print one integer — the maximum number of bosses your friend can place, considering all possible choices for ss and tt.

    Examples

    Input
    5 5
    1 2
    2 3
    3 1
    4 1
    5 2
    Output
    2
    Input
    4 3
    1 2
    4 3
    3 2
    Output
    3

    题意:一条路径上必经的边为关键边,现在让你找一条路径,使得其关键边最多,输出最多的数量。

    思路:如果一条路径上面有环,那么这个环的任意一条边都不是关键边。所以我们缩点,那么就算在一棵树上找最多的关键边,显然就算求直径。

    #include<bits/stdc++.h>
    #define ll long long 
    using namespace std;
    const int maxn=600010;
    int From[maxn],Laxt[maxn],To[maxn<<2],Next[maxn<<2],cnt;
    int low[maxn],dfn[maxn],times,q[maxn],head,scc_cnt,scc[maxn];
    vector<int>G[maxn];
    int dis[maxn],S,T,ans;
    void add(int u,int v)
    {
        Next[++cnt]=Laxt[u]; From[cnt]=u;
        Laxt[u]=cnt; To[cnt]=v;
    }
    void tarjan(int u,int fa)
    {
        dfn[u]=low[u]=++times; 
        q[++head]=u;
        for(int i=Laxt[u];i;i=Next[i]){
            if(To[i]==fa) continue;
            if(!dfn[To[i]]) {
                  tarjan(To[i],u);
                  low[u]=min(low[u],low[To[i]]);
            }
            else low[u]=min(low[u],dfn[To[i]]);
        }
        if(low[u]==dfn[u]){
            scc_cnt++;
            while(true){
                int x=q[head--];
                scc[x]=scc_cnt;
                if(x==u) break;
            }
        }
    }
    void dfs(int u,int f)
    {
        dis[u]=dis[f]+1;
        for(int i=0;i<G[u].size();i++){
            if(G[u][i]!=f) dfs(G[u][i],u);
        }
    }
    int main()
    {
        int N,M,u,v,i,j;
        scanf("%d%d",&N,&M);
        for(i=1;i<=M;i++){
            scanf("%d%d",&u,&v);
            add(u,v); add(v,u);
        }
        tarjan(1,0);
        for(i=1;i<=N;i++){
            for(j=Laxt[i];j;j=Next[j]){
               if(scc[i]!=scc[To[j]])
                 G[scc[i]].push_back(scc[To[j]]);
            }
        }
        dfs(1,0);
        for(i=1;i<=scc_cnt;i++) if(dis[i]>dis[S]) S=i;
        dfs(S,0);
        for(i=1;i<=scc_cnt;i++) ans=max(ans,dis[i]-1);
        printf("%d
    ",ans);
        return 0;
    }

    对于无向图的缩点:

    void tarjan(int u,int fa)
    {
        dfn[u]=low[u]=++times; 
        q[++head]=u;
        for(int i=Laxt[u];i;i=Next[i]){
            if(To[i]==fa) continue;
            if(!dfn[To[i]]) {
                  tarjan(To[i],u);
                  low[u]=min(low[u],low[To[i]]);
            }
            else low[u]=min(low[u],dfn[To[i]]);
        }
        if(low[u]==dfn[u]){
            scc_cnt++;
            while(true){
                int x=q[head--];
                scc[x]=scc_cnt;
                if(x==u) break;
            }
        }
    }

    对于有向图的缩点:二者唯一的区别就算有向图考虑横边,所以有个instack的判断。

    void tarjan(int u)
    {
        instk[u]=1;
        q[++head]=u;
        dfn[u]=low[u]=++times;
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i];
            if(!dfn[v]) {
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(instk[v])low[u]=min(low[u],dfn[v]);//无向图与有向图的区别
        }
        if(dfn[u]==low[u]){
            scc_cnt++;
            while(true){
                 int x=q[head--];
                 scc[x]=scc_cnt;
                 V[scc_cnt]+=w[x];
                 instk[x]=0;
                 if(x==u) break;
            }     
        }
    }
  • 相关阅读:
    [转]在自己的项目中调用别人的库的方法(static lib库,dynamic lib库以及dll动态库)
    前端、后台、客户端以及服务器
    C# 使用j
    C# Linq技术中SelectMany() 获取list对象的属性 汇总成为一个新的集合
    C# 集合的扩展方法-查询表达式GroupBy()的使用 转
    C# ASP.NET MVC中Filter过滤器的使用 通过注册到Global.asax注册为全局 过滤所有action
    C# ASP.NET MVC中有四种Filter 过滤器类型 通过标签 Attribute加到action上面
    C# 《Asp.Net Web Api 》-----路由机制 转
    C# ASP.NET MVC5路由系统机制详细讲解(转)
    MVC 自定义数据校验规则 Validation
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9238757.html
Copyright © 2011-2022 走看看