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 to v in G.
For each test case, output a single integer that is the size of the largest clique in T(G).
1 5 5 1 2 2 3 3 1 4 1 5 2
4
题目大意:
T组测试数据,给一张有向图G,求一个结点数最大的结点集,使得该结点中任意两个结点 u 和 v满足:要么 u 可以到达 v, 要么 v 可以到达 u(u 和 v 相互可达也可以)。
解题思路:
”同一个强连通分量中的点要么都选,要么不选。把强连通分量收缩点后得到SCC图,让每个SCC结点的权等于它的结点数,则题目转化为求SCC图上权最大的路径。由于SCC图是一个 DAG, 可以用动态规划求解。“
解题代码:
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <algorithm> using namespace std; const int maxn=1100; const int maxm=51000; struct edge{ int u,v,next; edge(int u0=0,int v0=0){ u=u0;v=v0; } }e[maxm]; int n,m,head[maxn],dfn[maxn],low[maxn],mark[maxn],w[maxn],color[maxn],dp[maxn],cnt,nc,index; vector <int> vec; vector <vector<int> > dfsmap; void addedge(int u,int v){ e[cnt]=edge(u,v);e[cnt].next=head[u];head[u]=cnt++; } void input(){ cnt=nc=index=0; scanf("%d%d",&n,&m); vec.clear(); for(int i=0;i<=n;i++){ w[i]=dfn[i]=0; mark[i]=false; color[i]=dp[i]=head[i]=-1; } int u,v; while(m-- >0){ scanf("%d%d",&u,&v); addedge(u,v); } } void tarjan(int s){ dfn[s]=low[s]=++index; mark[s]=true; vec.push_back(s); for(int i=head[s];i!=-1;i=e[i].next){ int d=e[i].v; if(!dfn[d]){ tarjan(d); low[s]=min(low[d],low[s]); }else if(mark[d]){ low[s]=min(low[s],dfn[d]); } } if(dfn[s]==low[s]){ nc++; int d; do{ d=vec.back(); vec.pop_back(); color[d]=nc; mark[d]=false; w[nc]++; }while(d!=s); } } int DP(int s){ if(dp[s]!=-1) return dp[s]; int ans=w[s]; for(int i=0;i<dfsmap[s].size();i++){ int d=dfsmap[s][i]; if(DP(d)+w[s]>ans) ans=DP(d)+w[s]; } return dp[s]=ans; } void solve(){ for(int i=1;i<=n;i++){ if(!dfn[i]) tarjan(i); } dfsmap.clear(); dfsmap.resize(nc+1); for(int i=0;i<cnt;i++){ int x=color[e[i].u],y=color[e[i].v]; if(x!=y){ dfsmap[x].push_back(y); //cout<<x<<"->"<<y<<endl; } } int ans=0; for(int i=1;i<=nc;i++){ if(DP(i)>ans) ans=DP(i); //cout<<i<<" "<<ans<<endl; } printf("%d\n",ans); } int main(){ int t; scanf("%d",&t); while(t-- >0){ input(); solve(); } return 0; }
uva 11324 The Largest Clique(图论-tarjan,动态规划),布布扣,bubuko.com
uva 11324 The Largest Clique(图论-tarjan,动态规划)
原文:http://blog.csdn.net/a1061747415/article/details/38380665