tarjan一直是我看了头大的问题,省选之前还是得好好系统的学习一下。我按照不同的算法在hdu上选题练习了一下,至少还是有了初步的认识。tarjan嘛,就是维护一个dfsnum[]和一个low[],在dfs树上处理图的连通性等问题。细节处的不同导致算法本身的不同作用。

 

  有向图强连通缩点:大体思路是维护一个栈,满足访问一个点就push到栈里面,当满足low[now]==dfn[now]时出栈,用dfn[]更新low[]当且仅当下一个点在栈内(注意不是递归栈)。  

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 2200
#define MAXV MAXN
#define MAXE MAXV*2
#define INF 0x3f3f3f3f
struct Edge
{
        int np;
        Edge *next;
}E[MAXE],*V[MAXV];
int tope=-1;
void addedge(int x,int y)
{
        E[++tope].np=y;
        E[tope].next=V[x];
        V[x]=&E[tope];
}
int status[MAXN];
int stack[MAXN],tops=-1;
int low[MAXN],dfn[MAXN],dfstime;
int top[MAXN];
void tarjan(int now)
{
        status[now]=1;
        stack[++tops]=now;
        low[now]=dfn[now]=++dfstime;
        Edge *ne;
        for (ne=V[now];ne;ne=ne->next)
        {
                if (status[ne->np]==1)
                {
                        low[now]=min(low[now],dfn[ne->np]);
                }else if (status[ne->np]==0)
                {
                        tarjan(ne->np);
                        low[now]=min(low[now],low[ne->np]);
                }
        }
        if (low[now]==dfn[now])
        {
                while (stack[tops]!=now)
                {
                        status[stack[tops]]=2;
                        top[stack[tops--]]=now;
                }
                status[stack[tops]]=2;
                top[stack[tops--]]=now;
        }
        //status[now]=2;
}
int a[MAXN];
int el[MAXE][2];
int degi[MAXN];
int cirv[MAXN];

int main()
{
        freopen("input.txt","r",stdin);
        int n,m,x,y,z;
        while (~scanf("%d%d",&n,&m))
        {
                for (int i=1;i<=n;i++)
                        scanf("%d",a+i);
                for (int i=1;i<=m;i++)
                {
                        scanf("%d%d",&x,&y);
                        addedge(x,y);
                        el[i][0]=x;
                        el[i][1]=y;
                }
                for (int i=1;i<=n;i++)
                        if (!dfn[i])
                                tarjan(i);
                for (int i=1;i<=m;i++)
                {
                        if (top[el[i][0]]!=top[el[i][1]])
                                degi[top[el[i][1]]]++;
                }
                memset(cirv,INF,sizeof(cirv[0])*(n+10));
                for (int i=1;i<=n;i++)
                        cirv[top[i]]=min(cirv[top[i]],a[i]);
                int ans2=0,ans1=0;
                for (int i=1;i<=n;i++)
                {
                        if (top[i]==i && !degi[top[i]])
                        {
                                ans1++;
                                ans2+=cirv[top[i]];
                        }
                }
                printf("%d %d\n",ans1,ans2);
                memset(V,0,sizeof(V[0])*(n+10));
                memset(dfn,0,sizeof(dfn[0])*(n+10));
                memset(degi,0,sizeof(degi[0])*(n+10));
                memset(status,0,sizeof(status[0])*(n+10));
                tope=-1;
                dfstime=0;
        }
}
hdu 1827

相关文章:

  • 2021-12-04
  • 2021-05-22
  • 2021-10-05
  • 2021-09-16
猜你喜欢
  • 2021-08-01
  • 2021-08-05
  • 2021-12-18
  • 2022-12-23
  • 2022-12-23
  • 2022-01-10
  • 2021-10-01
相关资源
相似解决方案