Uva-11324-The Largest Clique

求双联通分量后简单DP下就行了,白书上的一个题。唉,在dfs_clock应该先++,这里卡死了

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
const int maxn=1500;
const int maxm=1e5+100;
int e,n,m,head[maxn],nxt[maxm],pnt[maxm];
int dfs_clock,scc_cnt,sccno[maxn],dfn[maxn],lowlink[maxn];
int u[maxm],v[maxm],cnt[maxn],dp[maxn];
bool is[1001][1001];
stack<int> s;
void AddEdge(int u,int v)
{
    pnt[e]=v;nxt[e]=head[u];head[u]=e++;
}
void dfs(int u)
{
    dfn[u]=lowlink[u]=++dfs_clock;
    s.push(u);
    for(int i=head[u];i!=-1;i=nxt[i])
    {
        if(!dfn[pnt[i]])
        {
            dfs(pnt[i]);
            lowlink[u]=min(lowlink[u],lowlink[pnt[i]]);
        }
        else if(!sccno[pnt[i]])
        {
            lowlink[u]=min(lowlink[u],dfn[pnt[i]]);
        }
    }
    if(lowlink[u]==dfn[u])
    {
        scc_cnt++;
        for(;;)
        {
            int x=s.top();
            s.pop();
            sccno[x]=scc_cnt;
            cnt[scc_cnt]++;
            if(x==u)
                break;
        }
    }
}
void find_scc(int n)
{
    dfs_clock=scc_cnt=0;
    memset(sccno,0,sizeof(sccno));
    memset(dfn,0,sizeof(dfn));
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            dfs(i);
}
int DP(int u)
{
    if(dp[u])
        return dp[u];
    dp[u]=cnt[u];
    for(int i=head[u];i!=-1;i=nxt[i])
        dp[u]=max(dp[u],DP(pnt[i])+cnt[u]);
    return dp[u];
}
void rebuild()
{
    e=0;
    memset(is,0,sizeof(is));
    memset(head,-1,sizeof(head));
    memset(dp,0,sizeof(dp));
    for(int i=0;i<m;i++)
        if(sccno[u[i]]!=sccno[v[i]]&&!is[sccno[u[i]]][sccno[v[i]]])
        {
            is[sccno[u[i]]][sccno[v[i]]]=1;
            AddEdge(sccno[u[i]],sccno[v[i]]);
        }
    int ans=0;
    for(int i=1;i<=scc_cnt;i++)
    {
        ans=max(ans,DP(i));
       // printf("SSSS %d %d\n",i,cnt[i]);
    }
    printf("%d\n",ans);

}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        e=0;
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head));
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u[i],&v[i]);
            AddEdge(u[i],v[i]);
        }
        find_scc(n);
        rebuild();
    }
    return 0;
}


你可能感兴趣的:(SCC)