UVa 11234 The Largest Clique

找最长的连接的点的数量。用tarjan缩点,思考可知每一个强连通分量里的点要么都选,要么都不选(走别的路),可以动规解决。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<cstring>
 6 using namespace std;
 7 const int mxn=12000;
 8 int top,stack[mxn];
 9 bool inst[mxn];
10 int cnt,dnow; 
11 int dfn[mxn],low[mxn];
12 int belone[mxn];
13 int ptcnt[mxn];
14 int dp[mxn];
15 vector<int> e[mxn];//邻接表 
16 vector<int> pt[mxn];//缩点后的点集 
17 void clear(){
18     cnt=0;dnow=0;top=0;
19     memset(dfn,-1,sizeof(dfn));
20     memset(inst,false,sizeof(inst));
21     memset(dp,0,sizeof dp);
22     memset(ptcnt,0,sizeof ptcnt);
23     memset(belone,0,sizeof belone);
24     for(int i=1;i<mxn;i++) e[i].clear();
25     for(int i=1;i<mxn;i++) pt[i].clear();
26 }
27 int n,m;
28 void tarjan(int s){
29     int v=0,i;
30     dfn[s]=++dnow;
31     low[s]=dfn[s];
32     inst[s]=true; 
33     stack[++top]=s;
34     int si=e[s].size();
35     for(i=0;i<si;i++){
36         v=e[s][i];
37         if(dfn[v]==-1){
38             tarjan(v);
39             low[s]=min(low[v],low[s]);
40         }
41         else if(inst[v]){
42             low[s]=min(dfn[v],low[s]);
43         }
44     }
45     if(dfn[s]==low[s]){
46         cnt++;
47         do{
48             v=stack[top--];
49             belone[v]=cnt;
50             inst[v]=false;
51         }while(s!=v);
52     }
53     return;
54 }
55 int find(int x){//动规 
56     if(pt[x].size()==0)return dp[x]=ptcnt[x];
57     if(dp[x])return dp[x];
58     int mx=0;
59     for(int i=0;i<pt[x].size();i++){
60         mx=max(mx,find(pt[x][i]));
61     }
62     dp[x]=mx+ptcnt[x];
63     return dp[x];
64 }
65 void solve(){//统计缩完点之后的连通情况 
66     int i,j,k;
67     for(i=1;i<=n;i++){
68         ptcnt[belone[i]]++;
69         for(j=0;j<e[i].size();j++){
70             int v=e[i][j];
71             if(belone[i]!=belone[v])
72                 pt[belone[i]].push_back(belone[v]);
73         }
74     }
75     int ans=0;
76     for(i=1;i<=cnt;i++)ans=max(ans,find(i));
77     printf("%d\n",ans);
78     return;
79 }
80 int main(){
81     int T;
82     scanf("%d",&T);
83     while(T--){
84         scanf("%d%d",&n,&m);
85         clear();
86         int i,j;
87         int u,v;
88         for(i=1;i<=m;i++){
89             scanf("%d%d",&u,&v);
90             e[u].push_back(v);
91         }
92         for(i=1;i<=n;i++){//缩点 
93             if(dfn[i]==-1)tarjan(i);
94         }
95         solve();
96     }
97     return 0;
98 }

 

posted @ 2016-08-07 16:42  SilverNebula  阅读(192)  评论(0编辑  收藏  举报
AmazingCounters.com