zoukankan      html  css  js  c++  java
  • 9.20洛谷图论

    一。tanjian算法(强连通图)

    int s[MAXN], stop;
    int dfn[MAXN], low[MAXN];
    int scccnt, sccnum[MAXN];
    int dfscnt;
    
    inline void tarjan(int now){
        dfn[now] = low[now] = ++dfscnt;
        s[stop++] = now;
        for (int i = he[now]; i != 0 ; i = ne[i]){
            if (!dfn[ed[i]]) {
                tarjan(ed[i]);
                low[now] = min(low[now], low[ed[i]]);
            } else if(!sccnum[ed[i]]) {
                low[now] = min(low[now], dfn[ed[i]]);
            }
        }
    
        if (dfn[now] == low[now]) {
            scccnt++;
            do {
                sccnum[s[--stop]] = scccnt;
            } while(s[stop] != now);
        }
    }

    练习:(割点割边+缩点+dfs)模板:P3387

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 struct sb
     5 {
     6     int to,nx;
     7 }g[200001];
     8 int x[100001],y[100001],t[100001];
     9 int cnt,list[200001];
    10 void add(int x,int y)
    11 {
    12     g[++cnt].to=y; g[cnt].nx=list[x]; list[x]=cnt;
    13 }
    14 int dfn[100001],low[100001],num,stack[100010],top,color[100010],col,sum[100010],vis[100010];
    15 void tarjan(int x)
    16 {
    17     dfn[x]=++num;
    18     low[x]=num;
    19     vis[x]=1;
    20     stack[++top]=x;
    21     for (int i=list[x];i;i=g[i].nx)
    22     {
    23         int y=g[i].to;
    24         if (!dfn[y])
    25         {
    26             tarjan(y);
    27             low[x]=min(low[x],low[y]);
    28         }
    29         else if (vis[y]) low[x]=min(low[x],dfn[y]);
    30     }
    31     if (dfn[x]==low[x]) 
    32     {
    33         ++col;
    34         while (stack[top+1]!=x)
    35         {
    36             color[stack[top]]=col;
    37             sum[col]+=t[stack[top]];
    38             vis[stack[top--]]=false;
    39         }
    40     }
    41 }
    42 int f[100010];
    43 void dfs(int x)
    44 {
    45     if (f[x]) return;
    46     f[x]=sum[x];
    47     int maxsum=0;
    48     for (int i=list[x];i;i=g[i].nx)
    49     {
    50         int y=g[i].to;
    51         if (!f[y]) dfs(y);
    52         maxsum=max(maxsum,f[y]);
    53     }
    54     f[x]+=maxsum;
    55 }
    56 int main ()
    57 {
    58     int n,m;
    59     cin>>n>>m;
    60     for (int i=1;i<=n;i++) cin>>t[i];
    61     for (int i=1;i<=m;i++)
    62     {
    63         cin>>x[i]>>y[i];
    64         add(x[i],y[i]);
    65     }
    66     for (int i=1;i<=n;i++)
    67       if (!dfn[i]) tarjan(i);
    68     memset(g,0,sizeof(g));
    69     memset(list,0,sizeof(list));
    70     cnt=0;
    71     for (int i=1;i<=m;i++)
    72        if (color[x[i]]!=color[y[i]])
    73          add(color[x[i]],color[y[i]]);
    74     int ans=0;
    75     for (int i=1;i<=col;i++)
    76       if (!f[i])
    77       {
    78            dfs(i);
    79            ans=max(ans,f[i]);
    80       }
    81     cout<<ans;
    82     
    83 } 

    二。树的直径   树的重心(分治)

    int sz[MAXN];
    inline int dfs_sz(int now, int f){
        sz[now] = 1;
        for(int i = he[now]; i; i = ne[i]){
            Edge& e = ed[i];
            if(!vis[e.to] && e.to != f){
                sz[now] += dfs_sz(e.to, now);
            }
        }
        return sz[now];
    }
    
    inline int dfs_find(int now, int f, int tot){
        for(int i = he[now]; i; i = ne[i]){
            Edge& e = ed[i];
            if(!vis[e.to] && e.to != f){
                if(sz[e.to]*2 > tot) return dfs_find(e.to, now, tot);
            }
        }
        return now;
    }
    
    
    inline int findg(int s){
        dfs_sz(s, -1);
        return dfs_find(s, -1, sz[s]);
    }

    练习:POJ1655

    三。最近公共祖先

    (倍增LCA)枚举答案的二进制位

    int fa[maxn][20], dep[maxn], d[maxn];
    
    void build_lca(int now){
        for(int i = 1 ; i < 20 && fa[now][i] ; i++){
            fa[now][i] = fa[fa[now][i-1]][i-1];
        }
        
        for(int i = he[now]; i ; i = ne[i]){
            Edge &e = ed[i];
            if(e.to == fa[now][0])  continue;
            fa[e.to][0] = now;
            dep[e.to] = dep[now] + 1;
            d[e.to] = d[now] + e.dist;
            build_lca(e.to);
        }
    }
    
    int get_lca(int x,int y)
    {
        if(dep[x] != dep[y]){
            if(dep[y] > dep[x])  swap(X,y);
            
            for(int i = 19 ; i >= 0 ; i--){
                if(dep[fa[x][i]] >= dep[y])  x = fa[x][i];
            }
        }
        
        if(x == y)  return x;
        
        for(int i = 19 ; i >= 0 ; i--){
            if(fa[x][i] != fa[y][i]) {
                x = fa[x][i];
                y = fa[y][i];
            }
        }
        
        return fa[x][0];
    } 

    例题:P1073  P2746 P2860

  • 相关阅读:
    September 17th 2016 Week 38th Saturday
    【2016-09-16】UbuntuServer14.04或更高版本安装问题记录
    September 16th 2016 Week 38th Friday
    September 11th 2016 Week 38th Sunday
    September 12th 2016 Week 38th Monday
    September 10th 2016 Week 37th Saturday
    September 9th 2016 Week 37th Friday
    c++暂停
    八皇后问题
    ( 转转)Android初级开发第九讲--Intent最全用法(打开文件跳转页面等)
  • 原文地址:https://www.cnblogs.com/zyddd915/p/11558964.html
Copyright © 2011-2022 走看看