ZOJ - 3795 Grouping & UVA - 11324 The Largest Clique (强连通缩点+DAG最长路)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GYH0730/article/details/82318474

两道类型一样的套路题,附上zoj的代码,另外一道只需改一改数据范围就行了

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
const int MAXM = 300005;
//-----------------------有向图找强连通分量------------------------
struct Edge
{
    int to,Next;
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,top;
int scc;
bool Instack[MAXN];
int num[MAXN];
void init()
{
    tot = 0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
    edge[tot].to = v;
    edge[tot].Next = head[u];
    head[u] = tot++;
}
void Tarjan(int u)
{
    int v;
    Low[u] = DFN[u] = ++Index;
    Stack[top++] = u;
    Instack[u] = true;
    for(int i = head[u]; i != -1; i = edge[i].Next) {
        v = edge[i].to;
        if(!DFN[v]) {
            Tarjan(v);
            if(Low[u] > Low[v]) Low[u] = Low[v];
        }
        else if(Instack[v] && Low[u] > DFN[v])
            Low[u] = DFN[v];
    }
    if(Low[u] == DFN[u]) {
        scc++;
        do {
            v = Stack[--top];
            Instack[v] = false;
            Belong[v] = scc;
            num[scc]++;
        }
        while(v != u);
    }
}
void solve(int N)
{
    memset(DFN,0,sizeof(DFN));
    memset(Instack,false,sizeof(Instack));
    memset(num,0,sizeof(num));
    Index = scc = top = 0;
    for(int i = 1; i <= N; i++) {
        if(!DFN[i]) {
            Tarjan(i);
        }
    }
}
//-----------------------有向图找强连通分量------------------------
//-----------------------DAG最长路---------------------------------
int dp[MAXN];
vector<int> G[MAXN];
int DP(int u)
{
    int& ans = dp[u];
    if(ans >= 0) return ans;
    ans = num[u];
    for(int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        ans = max(ans,DP(v) + num[u]);
    }
    return ans;
}
//-----------------------DAG最长路---------------------------------
int main(void)
{
    int n,m,u,v,ans;
    while(scanf("%d %d",&n,&m) != EOF) {
        init();
        while(m--) {
            scanf("%d %d",&u,&v);
            addedge(u,v);
        }
        solve(n);
        for(int i = 1; i <= n; i++) G[i].clear();
        for(int i = 1; i <= n; i++) {
            u = Belong[i];
            for(int j = head[i]; j != -1; j = edge[j].Next) {
                v = Belong[edge[j].to];
                if(u != v) G[u].push_back(v);
            }
        }
        ans = 0;
        memset(dp,-1,sizeof(dp));
        for(int i = 1; i <= n; i++) {
            ans = max(ans,DP(i));
        }
        printf("%d\n",ans);
    }
    return 0;
}
/*
1
5 5
1 2
2 3
3 1
4 1
5 2
*/

猜你喜欢

转载自blog.csdn.net/GYH0730/article/details/82318474