uva 11324

这是有向图的最大团问题 ,  解决方法是:先求出scc的dag图, 再用dag动态规划来求最大团

#include
#include
#include
#include
#include
#include
using namespace std;

const int MAXN = 1100 ;

int pre[MAXN] , lowlink[MAXN] , sccno[MAXN] ;
int n = 0, m = 0, dfs_clock = 0, scc_cnt = 0 , vis[MAXN];
vector grap[MAXN] ;
stack s;
int d[MAXN] , scc_sum[MAXN];
int DAG[MAXN][MAXN];


void dfs(int u)
{
    lowlink[u] = pre[u] = ++dfs_clock ;
    s.push(u);
    for(int i = 0 ; i < grap[u].size() ; i++)
    {
        int v = grap[u][i] ;
        if(!pre[v])
        {
            dfs(v) ;
             lowlink[u] = min( lowlink[v] , lowlink[u] );
        }
        else if(!sccno[v])
        {
              lowlink[u] = min(lowlink[u] , pre[v]) ; //在这里不是和lowlink[v]比较 ,是因为此时lowlink[v] == pre[v] 。
            // 因为v这个点首先不属于其他任何一个强连通分量 , 所以就可以判断出v和u是的祖先 。 就是说dfs是先到达v , 然后再从v来到了u 。
        }
    }
    if(lowlink[u] == pre[u]) 
    {
        scc_cnt++;
        for(; ;)
        {
            int x = s.top();
            s.pop() ;
            sccno[x] = scc_cnt;
        //    sum += 1;
            if(x == u)  break;
        }
    //    scc_sum[scc_cnt] = sum ;
    }
}


void find_scc()
{
    memset(pre , 0 , sizeof(pre));
    memset(lowlink , 0 , sizeof(lowlink));
    memset(sccno , 0 , sizeof(sccno));
    memset(scc_sum , 0 , sizeof(scc_sum));
    memset(vis , 0 , sizeof(vis));
    dfs_clock = scc_cnt = 0 ;
    for(int i = 1; i <= n; i++)
        if(!pre[i])  dfs(i);
}


int dp(int v)

      
        if(d[v]) return d[v]; 
        int Max = 0; 
        for(int i = 1;i <= scc_cnt;i++) 
            if(DAG[v][i])
                Max = max(Max,dp(i)); 
        return d[v] = scc_sum[v] + Max; 
   


int main()
{
    int p ;
    cin>>p;
    while(p--)
    {
        int i , j , x , y;
        for(i = 1; i <= n ; i++)
            grap[i].clear();
        cin>>n>>m;
        for(i = 0 ; i < m; i++)
        {
            scanf("%d %d" , &x , &y);
            grap[x].push_back(y);
        }
        find_scc();
        for(i = 1; i <= n; i++)
            scc_sum[sccno[i]] += 1;
        memset(DAG , 0 , sizeof(DAG));
        for(i = 1; i <= n; i++)
            for(j = 0 ; j < grap[i].size() ; j++)
            {
                x = grap[i][j];
                if(sccno[i] != sccno[x])  DAG[sccno[i]][sccno[x]] = 1;
            }
        memset(d , 0 , sizeof(d));
        int max_sum = 0;
       
        for(i = 1; i <= scc_cnt; i++)
        {
            x = dp(i);
            if(x > max_sum)  max_sum = x ;
        }
        cout<<max_sum<<endl;
    }
    return 0;
}


每次写代码时 , 都要谨慎、谨慎、再谨慎!!!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值