Uva 11324 强连通分量求解 + 缩点——有向无环图求最长路径

http://vjudge.net/contest/view.action?cid=48251#problem/E

Problem B: The Largest Clique

Given a directed graph G, consider the following transformation. First, create a new graph T(G) to have the same vertex set as G. Create a directed edge between two vertices u and v in T(G) if and only if there is a path between u and v in G that follows the directed edges only in the forward direction. This graph T(G) is often called the transitive closure of G.

We define a clique in a directed graph as a set of vertices U such that for any two vertices u and v in U, there is a directed edge either from u to v or from v to u (or both). The size of a clique is the number of vertices in the clique.

The number of cases is given on the first line of input. Each test case describes a graph G. It begins with a line of two integers n and m, where 0 ≤ n ≤ 1000 is the number of vertices of G and 0 ≤ m ≤ 50,000 is the number of directed edges of G. The vertices of G are numbered from 1 to n. The following m lines contain two distinct integers u and v between 1 and n which define a directed edge from u tov in G.

For each test case, output a single integer that is the size of the largest clique in T(G).

Sample input

1
5 5
1 2
2 3
3 1
4 1
5 2

Output for sample input

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

解题思路:不难发现在最优的方案中,同一个强连通分量中的点要么都选,要么都不选。把强连通分量搜索点后得到一个无环图,每一个节点的权等于它的节点数,则题目转化为求该无环图上权最大的路径。可用动态规划求解。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <stack>
using namespace std;
const int N=1002;
const int M=50005;
struct note
{
    int u;
    int v;
    int next;
} edge[M],a[M];
int head[N],ip,in[N],Q[N],dfn[N],low[N],sccno[N],dp[N];
bool _map[N][N];
int n,m,stamp,cnt_edge,scc_cnt,top,scc_val[N];
stack <int> q;
void addedge(int u,int v)
{
    edge[ip].v=v;
    edge[ip].next=head[u];
    head[u]=ip++;
}
void init()
{
    scc_cnt=0;
    stamp=0;
    memset(in,0,sizeof(in));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(scc_val,0,sizeof(scc_val));
    memset(_map,0,sizeof(_map));
    memset(dp,0,sizeof(dp));
    memset(sccno,0,sizeof(sccno));
    memset(head,-1,sizeof(head));
    ip=0;
}
void tarjan(int u)
{
    dfn[u]=low[u]=++stamp;
    q.push(u);
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        int v=edge[i].v;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!scc_val[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u])
    {
        scc_cnt++;
        int x;
        do
        {
            x=q.top();
            q.pop();
            scc_val[x]=scc_cnt;
            sccno[scc_cnt]++;
        }
        while(x!=u);
    }
}
void DP()
{
    int car=0,cdr=0;
    /*for(int i=1;i<=scc_cnt;i++)
        printf("(%d %d)\n",in[i],sccno[i]);*/
    for(int i=1; i<=scc_cnt; i++)
    {
        if(in[i]==0)
            Q[car++]=i,dp[i]=sccno[i];
    }
    while(car!=cdr)
    {
        int u=Q[cdr++];
        for(int k=head[u]; k!=-1; k=edge[k].next)
        {
            int v=edge[k].v;
            dp[v]=max(dp[v],dp[u]+sccno[v]);
            if(--in[v]==0)
                Q[car++]=v;
        }
    }
}
int main()
{
    int T,u,v;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init();
        for(int i=0; i<m; i++)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v);
            a[i].u=u,a[i].v=v;
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i])
               tarjan(i);
        memset(head,-1,sizeof(head));
        ip=0;
        for(int i=0; i<m; i++)
        {
            u=a[i].u,v=a[i].v;
            if(scc_val[u]!=scc_val[v]&&!_map[scc_val[u]][scc_val[v]])
            {
                addedge(scc_val[u],scc_val[v]);
                in[scc_val[v]]++;
                _map[scc_val[u]][scc_val[v]]=true;
            }
        }
        DP();
        int ans = 0;
        for (int i = 1; i <= scc_cnt; i++) ans = max(ans, dp[i]);
        printf("%d\n", ans);
    }
    return 0;
}


你可能感兴趣的:(Uva 11324 强连通分量求解 + 缩点——有向无环图求最长路径)