UVA11324_The Largest Clique


極大團。即求一個最大點集,使得點集中的任意兩個點u,v至少存在u->v,或者v->u的路徑。

是這樣做的,求出所有的聯通分量,然后整個圖就變成了無環圖,把原來若干個點縮點,點權為分量的點數。這樣相當於找一條權值最大的路徑,因為無環了,所以這個可以通過先拓撲排序然后dp解決。

 

這里重點說一下自己遇到的坑吧。

d[cur]=low[cur]=++dfsclock;  絕不能是  d[cur]=low[cur]=d[fa]+1;

后者是錯的。

我思考了好久后來才發現問題。如圖:

假設我們按照d[fa]+1的方法來打標記,那么當路徑為1->2->3時候,遞歸返回的時候low[1]=1,low[2]=1,low[3]=2,而此時去訪問4點,此時low[4]最少也只能是2,那么從程序的角度來說,也就認為了4是單獨的強聯通分量,這是不對的。

但是如果我們按照++dfsclock的方法來打標記,那么low[1]=1,low[2]=1,low[3]=2,low[4]=2,但是此時d[4]=4,可以判斷出不是一個單獨的強連通分量。主要是通過++dfsclock可以判斷是否以前被訪問過,這里與源點距離無關,特別注意了。

 

 

召喚代碼君:

 

 

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 1010
#define maxm 202000
using namespace std;

int first[maxn],next[maxm],to[maxm],edge;
int low[maxn],d[maxn],belong[maxn],scc;
int U[maxm],V[maxm],stack[maxn],top;
int f[maxn],sum[maxn],Q[maxn];
int n,m,T,ans,dfsclock;

bool cmp(int q1,int q2)
{
    return d[q1]>d[q2];
}

void _init()
{
    dfsclock=ans=top=scc=0,edge=-1;
    for (int i=1; i<=n; i++) first[i]=-1,low[i]=d[i]=belong[i]=0;
}

void addedge(int uu,int vv)
{
    edge++;
    to[edge]=vv,next[edge]=first[uu],first[uu]=edge;
}

void dfs(int cur,int fa)
{

    d[cur]=low[cur]=++dfsclock;
    stack[++top]=cur;
    for (int i=first[cur]; i!=-1; i=next[i])
    {
        if (belong[to[i]]) continue;
        if (!d[to[i]]) dfs(to[i],cur);
        low[cur]=min(low[cur],low[to[i]]);
    }
    if (low[cur]>=d[cur])
        for (scc++,f[scc]=0;;)
        {
            belong[stack[top--]]=scc;
            f[scc]++;
            if (stack[top+1]==cur) break;
        }
}

int get(int x)
{
    if (d[x]!=0) return d[x];
    if (first[x]==-1) return d[x]=1;

    d[x]=0;
    for (int i=first[x]; i!=-1; i=next[i])
        d[x]=max(d[x],get(to[i])+1);

    return d[x];
}

int main()
{
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&n,&m);
        _init();
        for (int i=1; i<=m; i++)
        {
            scanf("%d%d",&U[i],&V[i]);
            addedge(U[i],V[i]);
        }
        for (int i=1; i<=n; i++)
            if (!d[i]) dfs(i,0);
        edge=-1;
        for (int i=1; i<=scc; i++) first[i]=-1,d[i]=0;
        for (int i=1; i<=m; i++)
            if (belong[U[i]]!=belong[V[i]])
                addedge(belong[U[i]],belong[V[i]]);

        for (int i=1; i<=scc; i++)
        {
            Q[i]=i,sum[i]=0;
            if (!d[i]) d[i]=get(i);
        }
        sort(Q+1,Q+1+scc,cmp);
        for (int i=1; i<=scc; i++)
        {
            sum[Q[i]]+=f[Q[i]];
            ans=max(ans,sum[Q[i]]);
            for (int j=first[Q[i]]; j!=-1; j=next[j])
                sum[to[j]]=max(sum[to[j]],sum[Q[i]]);
        }
        printf("%d\n",ans);
    }
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM