1. 程式人生 > >UVA11324 The Largest Clique (強連通縮點+DP最長路)

UVA11324 The Largest Clique (強連通縮點+DP最長路)

<題目連結>

題目大意:

給你一張有向圖 G,求一個結點數最大的結點集,使得該結點集中的任意兩個結點 u 和 v 滿足:要麼 u 可以達 v,要麼 v 可以達 u(u,v相互可達也行)。

解題分析:

該點集需滿足兩個要求:1.任意兩點至少有一方能夠到達另外一點;2.點數儘可能的多。

通過畫圖分析可以知道,對於那些強連通分量來說,要不就全部加入該點集,要不就全部不能加入,所以直接對原圖進行縮點,進行重新構圖。然後,根據重新構造的DAG圖我們可以知道,要使該點集中任意兩點至少有一方能夠到達另外一點,並且要求點數儘可能的多,可以發現,其實就是讓我們求縮點後的最長路。

 1
#include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 7 #define pb push_back 8 #define clr(a,b) memset(a,b,sizeof(a)) 9 #define rep(i,s,t) for(int i=s;i<=t;i++) 10 const int N = 1e3+10,M = 5e4+10; 11 int
n,m,tot,tott,top,scc; 12 int head[N],belong[N],dfn[N],low[N],stk[N],instk[N],dp[N],cnt[N]; 13 vector<int>G[N]; 14 struct Edge{ 15 int to,next; 16 }edge[M]; 17 void init(){ 18 rep(i,0,n)G[i].clear(); 19 tot=scc=top=tott=0; 20 clr(head,-1);clr(low,0);clr(dfn,0);clr(stk,0);clr(instk,0
);clr(belong,0);clr(dp,0);clr(cnt,0); 21 } 22 void addedge(int u,int v){ 23 edge[++tot].to=v,edge[tot].next=head[u]; 24 head[u]=tot; 25 } 26 void Tarjan(int u){ //進行縮點 27 dfn[u]=low[u]=++tott; 28 stk[++top]=u;instk[u]=1; 29 for(int i=head[u];~i;i=edge[i].next){ 30 int v=edge[i].to; 31 if(!dfn[v]){ 32 Tarjan(v); 33 low[u]=min(low[u],low[v]); 34 }else if(instk[v])low[u]=min(low[u],dfn[v]); 35 } 36 if(dfn[u]==low[u]){ 37 scc++; 38 while(true){ 39 int v=stk[top--]; 40 instk[v]=0; 41 belong[v]=scc; 42 cnt[scc]++; 43 if(v==u)break; 44 } 45 } 46 } 47 //記憶化搜尋求以u為起點的最長路,點權為"點"中點的個數 48 int DFS(int u){ 49 if(dp[u])return dp[u]; 50 int ans=cnt[u]; 51 for(int i=0;i<G[u].size();i++){ 52 int v=G[u][i]; 53 ans=max(ans,DFS(v)+cnt[u]); 54 } 55 return dp[u]=ans; 56 } 57 int main(){ 58 int T;scanf("%d",&T);while(T--){ 59 init(); 60 scanf("%d%d",&n,&m); 61 rep(i,1,m){ 62 int u,v;scanf("%d%d",&u,&v); 63 addedge(u,v); 64 } 65 rep(i,1,n) 66 if(!dfn[i])Tarjan(i); 67 //對圖進行縮點,重新構圖 68 rep(u,1,n) for(int i=head[u];~i;i=edge[i].next){ 69 int v=edge[i].to; 70 if(belong[u]!=belong[v]) 71 G[belong[u]].pb(belong[v]); 72 } 73 int ans=0; 74 rep(i,1,scc) 75 ans=max(ans,DFS(i)); //求縮點後圖的最長路 76 printf("%d\n",ans); 77 } 78 }

 

 

2018-11-28