首页 > 代码库 > UVA 11324.The Largest Clique tarjan缩点+拓扑dp

UVA 11324.The Largest Clique tarjan缩点+拓扑dp

题目链接:https://vjudge.net/problem/UVA-11324

题意:求一个有向图中结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相互可达也可以)。

思路:同一个强联通分量中满足结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相互可达也可以)。把强联通分量收缩点后得到scc图,让每个scc结点的权值等于他的结点数,则求scc图上权最大的路径。拓扑dp,也可以直接bfs,但是要建立一个新的起点,连接所有入度为0的结点。

代码:

技术分享
#include<bits/stdc++.h>#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<map>#include<queue>#include<stack>#include<vector>using namespace std;typedef long long ll;const int MAXN=2e5+100,INF=0x3f3f3f3f,MOD=1e9+7;map<int,vector<int> >G;int pre[MAXN],lowlink[MAXN],sccno[MAXN],dfs_color,scc_cut;stack<int>S;map<int,vector<int> >NG;int deg[MAXN];int in[MAXN];void dfs(int u){    pre[u]=lowlink[u]=++dfs_color;    S.push(u);    for(int i=0; i<G[u].size(); i++)    {        int v=G[u][i];        if(!pre[v])        {            dfs(v);            lowlink[u]=min(lowlink[u],lowlink[v]);        }        else if(!sccno[v])            lowlink[u]=min(lowlink[u],lowlink[v]);    }    if(lowlink[u]==pre[u])    {        scc_cut++;        while(!S.empty())        {            int x=S.top();            S.pop();            sccno[x]=scc_cut;            deg[scc_cut]++;            if(x==u) break;        }    }}void find_scc(int n){    dfs_color=scc_cut=0;    memset(pre,0,sizeof(pre));    memset(sccno,0,sizeof(sccno));    memset(deg,0,sizeof(deg));    for(int i=1; i<=n; i++)        if(!pre[i]) dfs(i);}void re_build(int n){    for(int i=1; i<=scc_cut; i++) in[i]=0,NG[i].clear();    for(int u=1; u<=n; u++)    {        for(int i=0; i<G[u].size(); i++)        {            int v=G[u][i];            if(sccno[u]==sccno[v]) continue;            in[sccno[v]]++;            NG[sccno[u]].push_back(sccno[v]);        }    }    for(int i=1; i<=n; i++) G[i].clear();}queue<int>q;int ans[MAXN];void topsort(){    memset(ans,0,sizeof(ans));    for(int i=1; i<=scc_cut; i++)        if(in[i]==0) ans[i]=deg[i],q.push(i);    while(!q.empty())    {        int u=q.front();        q.pop();        for(int i=0; i<NG[u].size(); i++)        {            int v=NG[u][i];            ans[v]=max(ans[v],ans[u]+deg[v]);            in[v]--;            if(in[v]==0) q.push(v);        }    }}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n,m;        scanf("%d%d",&n,&m);        for(int i=1; i<=m; i++)        {            int u,v;            scanf("%d%d",&u,&v);            G[u].push_back(v);        }        find_scc(n);        re_build(n);        topsort();        int Max=0;        for(int i=1; i<=scc_cut; i++)            Max=max(Max,ans[i]);        cout<<Max<<endl;    }    return 0;}
tarjan缩点+拓扑dp

 

UVA 11324.The Largest Clique tarjan缩点+拓扑dp