zoukankan      html  css  js  c++  java
  • CF732 F Tourist Reform——边双连通分量

    题目:http://codeforces.com/contest/732/problem/F

    首先把边双缩点,边双内部 dfs 一个顺序一定是可以从每个点走到边双内部所有点的,因为它是以环为基本单位;

    然后对于缩点之后的图,找到 siz 最大的点作为根 dfs,再连反边,那么只有 siz 最大的那个点只能走到自己内部,就可以使答案最大;

    结构体要开得精细一点,防止爆空间?还是什么奇奇怪怪的错误之类的...

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=4e5+5;
    int n,m,hd[maxn],ct=1,cnt=1,dfn[maxn],low[maxn],tim,col[maxn],cr,siz[maxn];
    int sta[maxn],top,head[maxn];
    bool vis[maxn];
    //struct N{
    //    int to,nxt,bh,u,v,f;
    //    N(int t=0,int n=0,int b=0):to(t),nxt(n),bh(b) {}
    //}ed[maxn<<1],e[maxn],edge[maxn<<1];//这样写会爆空间?! 
    struct N{
        int to,nxt,bh;
        N(int t=0,int n=0,int b=0):to(t),nxt(n),bh(b) {}
    }ed[maxn<<1],edge[maxn<<1];
    struct E{int u,v,f;}e[maxn];
    void add(int x,int y,int b){ed[++ct]=N(y,hd[x],b); hd[x]=ct;}
    void add2(int x,int y,int b){edge[++cnt]=N(y,head[x],b); head[x]=cnt;}
    void tarjan(int x,int f)
    {
        dfn[x]=low[x]=++tim; vis[x]=1; sta[++top]=x; 
        for(int i=hd[x];i;i=ed[i].nxt)
        {
            int u=ed[i].to;
            if(u==f)continue;
            if(!dfn[u]) tarjan(u,x),low[x]=min(low[x],low[u]);
            else if(vis[u]) low[x]=min(low[x],dfn[u]);
        }
        if(dfn[x]==low[x])
        {
            cr++;
            while(sta[top]!=x)
            {
                int y=sta[top]; top--;
                vis[y]=0; col[y]=cr; siz[cr]++;
            }
            top--; vis[x]=0; col[x]=cr; siz[cr]++;
        }
    }
    void dfs(int x)
    {
        vis[x]=1;
        for(int i=head[x],u,eg;i;i=edge[i].nxt)
        {
            if(vis[u=edge[i].to])continue;
            if(x==col[e[eg=edge[i].bh].u]) e[eg].f=0;
            else e[eg].f=1;
            dfs(u);
        }
    }
    void dfs2(int x)
    {
        vis[x]=1;
        for(int i=hd[x],u,eg;i;i=ed[i].nxt)
        {
            u=ed[i].to;
            if(col[u]!=col[x])continue;
            if(x==e[eg=ed[i].bh].u) e[eg].f=1;
            else e[eg].f=0;
            if(!vis[u])dfs2(u);
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&e[i].u,&e[i].v);
            add(e[i].u,e[i].v,i); add(e[i].v,e[i].u,i);
        }
        for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i,0);
        memset(vis,0,sizeof vis);
        for(int i=1;i<=n;i++) if(!vis[i])dfs2(i);
        for(int i=1,u,v;i<=ct;i++)
            if((u=col[ed[i].to])!=(v=col[ed[i^1].to]))add2(u,v,ed[i].bh),add2(v,u,ed[i].bh);
        int rt=0,mx=0;
        for(int i=1;i<=cr;i++)
            if(siz[i]>mx)mx=siz[i],rt=i;
        printf("%d
    ",mx);
        memset(vis,0,sizeof vis);
        dfs(rt);
        for(int i=1;i<=m;i++)
        {
            if(e[i].f==1)printf("%d %d
    ",e[i].u,e[i].v);
            else printf("%d %d
    ",e[i].v,e[i].u);
        }
        return 0;
    }
  • 相关阅读:
    类和对象
    数组
    随笔3
    设计把所有的奇数移动到所有偶数前面的算法
    选择排序
    队列的链式存储结构
    循环队列
    一起玩算法(把所有相同的数字后移)
    判断序列B是否是序列A的连续子序列
    power bi创建切片器导航
  • 原文地址:https://www.cnblogs.com/Zinn/p/9279582.html
Copyright © 2011-2022 走看看