标签:tar class blank 自己的 mes std for ref ==
题意:从有向图G中找到一个最大的点集,使得该点集中任意两个结点u,v满足u可达v或v可达u。
解法:先把同处于一个强连通分量中的结点合并(缩点),得到一张DAG图,在DAG上dp即可。
感觉自己的建图写得好丑啊,一直在纠结用数组还是结构体~~
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 const int N=1e5+10; 5 int head[N],nxt[N],to[N],ne,n,m; 6 void addedge(int* head,int u,int v) { 7 nxt[ne]=head[u],to[ne]=v,head[u]=ne++; 8 } 9 int dfn[N],low[N],scc[N],sta[N],nscc,nsta,tot,siz[N]; 10 int head2[N]; 11 12 void dfs(int u) { 13 dfn[u]=low[u]=++tot; 14 sta[nsta++]=u; 15 for(int e=head[u]; ~e; e=nxt[e]) { 16 int v=to[e]; 17 if(!dfn[v])dfs(v),low[u]=min(low[u],low[v]); 18 else if(!scc[v])low[u]=min(low[u],dfn[v]); 19 } 20 if(low[u]==dfn[u]) { 21 nscc++; 22 for(; !scc[u]; scc[sta[--nsta]]=nscc); 23 } 24 } 25 26 void getscc() { 27 memset(dfn,0,sizeof dfn); 28 memset(scc,0,sizeof scc); 29 tot=nscc=nsta=0; 30 for(int i=1; i<=n; ++i)if(!dfn[i])dfs(i); 31 } 32 33 int d[N]; 34 35 int dp(int u) { 36 if(~d[u])return d[u]; 37 int x=0; 38 for(int e=head2[u]; ~e; e=nxt[e]) { 39 int v=to[e]; 40 x=max(x,dp(v)); 41 } 42 return d[u]=siz[u]+x; 43 } 44 45 int main() { 46 int T; 47 scanf("%d",&T); 48 while(T--) { 49 memset(head,-1,sizeof head); 50 memset(head2,-1,sizeof head2); 51 ne=0; 52 scanf("%d%d",&n,&m); 53 while(m--) { 54 int u,v; 55 scanf("%d%d",&u,&v); 56 addedge(head,u,v); 57 } 58 getscc(); 59 memset(siz,0,sizeof siz); 60 for(int u=1; u<=n; ++u)siz[scc[u]]++; 61 for(int u=1; u<=n; ++u) { 62 for(int e=head[u]; ~e; e=nxt[e]) { 63 int v=to[e]; 64 if(scc[u]!=scc[v])addedge(head2,scc[u],scc[v]); 65 } 66 } 67 memset(d,-1,sizeof d); 68 int ans=0; 69 for(int i=1; i<=nscc; ++i)ans=max(ans,dp(i)); 70 printf("%d\n",ans); 71 } 72 return 0; 73 }
UVA - 11324 The Largest Clique (强连通缩点+dp)
标签:tar class blank 自己的 mes std for ref ==
原文地址:https://www.cnblogs.com/asdfsag/p/10281549.html