• 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

  • 相关阅读:
    zend studio中安装Emmet插件后迅速编写html的方法
    ZendStudio 代码调试
    PHP中循环结构之foreach循环语句
    【题解】物流运输 [ZJ2006] [P1772] [BZOJ1003]
    【题解】最大 M 子段和 Max Sum Plus Plus [Hdu1024] [51nod1052]
    【题解】最长递增路径 [51nod1274]
    【题解】与查询 [51nod1406]
    【题解】选数字 [51nod1354]
    【题解】逆序排列 [51nod1020]
    【题解】整数划分 [51nod1201] 整数划分 V2 [51nod1259]
  • 原文地址:https://www.cnblogs.com/zyddd915/p/11558964.html
Copyright © 2020-2023  润新知