• tarjan代码


    还有五天就是NOIP2018了……本蒟蒻还要复习期中考试,因此实在没有时间写博客了(各种找借口)。这里就放一下代码

    //Tarjan缩点
    //题目描述:给一个有向图。每个点有一个权值,求权值和最大的路径的权值和
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<stack>
    #include<queue>
    #define MAXN 10005
    #define MAXM 100005
    using namespace std;
    
    inline int read()
    {
        int f=1,x=0;
        char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int n,m;
    int cnt,num,tot,ans;
    int u[MAXM],v[MAXM],head[MAXN],nxt[MAXM];//邻接表部分 
    int dfn[MAXN],low[MAXN];//tarjan部分 
    bool book[MAXN];
    stack <int> s;
    int p[MAXN],sd[MAXN],in_d[MAXN],dis[MAXN];//缩点+拓扑部分 
    queue <int> q;
    
    void add(int x,int y)
    {
        u[++cnt]=x;//存起点以供后续重新建图使用 
        v[cnt]=y;
        nxt[cnt]=head[x];
        head[x]=cnt;
    }
    
    void tarjan(int x)
    {
        dfn[x]=low[x]=++num;
        book[x]=1;
        s.push(x);
        for(int i=head[x];i;i=nxt[i])//标准tarjan 
        {
            int t=v[i];
            if(!dfn[t])
            {
                tarjan(t);
                low[x]=min(low[x],low[t]);
            }
            else if(book[t])
                low[x]=min(low[x],dfn[t]);
        }
        if(low[x]==dfn[x])
        {
            tot++;
            while(s.top()!=x)
            {
                int y=s.top();
                book[y]=0;
                p[x]+=p[y];//缩点的权值 
                sd[y]=x;//缩点标记 
                s.pop();
            }
            book[x]=0;
            sd[x]=x;
            s.pop();
        }
    }
    
    int main()
    {
        int i;
        int x,y;
        n=read(); m=read();
        for(i=1;i<=n;i++) p[i]=read();
        for(i=1;i<=m;i++)
        {
            x=read();
            y=read();
            add(x,y);//有向图 
        }
        for(i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i);
    
        memset(head,0,sizeof(head));
        memset(nxt,0,sizeof(nxt));
        for(i=1;i<=m;i++)//将缩后的点重新建图 
        {
            x=sd[u[i]],y=sd[v[i]];
            if(x!=y)
            {
                add(x,y);
                in_d[y]++;//每个点的入度(拓扑使用) 
            }
        }
        for(i=1;i<=n;i++)//利用拓扑搞dp,求最大权值路径 
        {
            if(sd[i]==i && !in_d[i])
            {
                q.push(i);
                dis[i]=p[i];//记得要把自己开始时的权值设成点权 
            }
        }
        while(!q.empty())
        {
            int x=q.front(); q.pop();
            for(i=head[x];i;i=nxt[i])
            {
                int t=v[i];
                dis[t]=max(dis[t],dis[x]+p[t]);
                in_d[t]--;
                if(!in_d[t]) q.push(t);//入度等于零,根据拓扑,入队 
            }
        }
        for(i=1;i<=n;i++)
            ans=max(ans,dis[i]);
        printf("%d",ans);
        return 0;
    }
        


    //Tarjan求割点
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 20005
    #define MAXM 200005
    using namespace std;
    
    inline int read()
    {
        int f=1,x=0;
        char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int n,m;
    int cnt,num,ans;
    int v[MAXM],head[MAXN],nxt[MAXM];
    int dfn[MAXN],low[MAXN];
    bool cut[MAXN];
    int i,j;
    
    void add(int a,int b)
    {
        v[++cnt]=b;
        nxt[cnt]=head[a];
        head[a]=cnt;
    }
    
    void tarjan(int x,int fa)
    {
        int Child=0;
        dfn[x]=low[x]=++num;
        for(int i=head[x];i;i=nxt[i])
        {
            int nx=v[i];
            if(!dfn[nx])
            {
                tarjan(nx,fa);
                low[x]=min(low[x],low[nx]);
                Child++;
                if(x!=fa && dfn[x]<=low[nx])
                    cut[x]=1;
            }
            else low[x]=min(low[x],dfn[nx]); //这行不要写错
        }
        if(x==fa && Child>=2)
            cut[x]=1;
    }
    
    int main()
    {
        int i;
        int a,b;
        n=read(); m=read();
        for(i=1;i<=m;i++)
        {
            a=read();
            b=read();
            add(a,b);
            add(b,a);
        }
        for(i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i,i);
        for(i=1;i<=n;i++)
            if(cut[i]) ans++;
        printf("%d
    ",ans);
        for(i=1;i<=n;i++)
            if(cut[i])
                printf("%d ",i);
        return 0;
    }

    ~NOIP2018 加油~

  • 相关阅读:
    Cider扩展架构:AttributeTable和AttributeTableBuilder
    VS编译时自动引用Debug|Release版本的dll
    扩展Oozie
    使用正则表达式找出不包含特定字符串的条目
    重构时机和重构方法之间的对应关系
    Javascript 果然存在所谓的预编译,例证:
    程序员眼中的UML(2)克服用例图的恐惧
    Hortonworks宣布一款Hadoop数据平台
    .NET Framework 4现已支持LocalDB
    REST API用得也痛苦
  • 原文地址:https://www.cnblogs.com/llllllpppppp/p/9903998.html
Copyright © 2020-2023  润新知