码迷,mamicode.com
首页 > 其他好文 > 详细

UVA11324 The Largest Clique —— 强连通分量 + 缩点 + DP

时间:2017-11-11 22:16:07      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:turn   题目   false   names   ack   memset   mes   scan   log   

 

题目链接:https://vjudge.net/problem/UVA-11324

 

技术分享

技术分享

 

题解:

 

 

代码一:

技术分享
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 #define ms(a,b) memset((a),(b),sizeof((a)))
 13 using namespace std;
 14 typedef long long LL;
 15 const double EPS = 1e-8;
 16 const int INF = 2e9;
 17 const LL LNF = 2e18;
 18 const int MAXM = 5e4+10;
 19 const int MAXN = 1e3+10;
 20 
 21 struct Edge
 22 {
 23     int to, next;
 24 }edge[MAXM], edge0[MAXM];   //edge为初始图, edge0为重建图
 25 int tot, head[MAXN], tot0, head0[MAXN];
 26 
 27 int Index, dfn[MAXN], low[MAXN];
 28 int top, Stack[MAXN], instack[MAXN];
 29 int scc, belong[MAXN], num[MAXN];
 30 int dp[MAXN];
 31 
 32 void addedge(int u, int v, Edge edge[], int head[], int &tot)
 33 {
 34     edge[tot].to = v;
 35     edge[tot].next = head[u];
 36     head[u] = tot++;
 37 }
 38 
 39 void Tarjan(int u)
 40 {
 41     dfn[u] = low[u] = ++Index;
 42     Stack[top++] = u;
 43     instack[u] = true;
 44     for(int i = head[u]; i!=-1; i = edge[i].next)
 45     {
 46         int v = edge[i].to;
 47         if(!dfn[v])
 48         {
 49             Tarjan(v);
 50             low[u] = min(low[u], low[v]);
 51         }
 52         else if(instack[v])
 53             low[u] = min(low[u], dfn[v]);
 54     }
 55 
 56     if(dfn[u]==low[u])
 57     {
 58         int v;
 59         scc++;
 60         do
 61         {
 62             v = Stack[--top];
 63             instack[v] = false;
 64             belong[v] = scc;
 65             num[scc]++;
 66         }while(v!=u);
 67     }
 68 }
 69 
 70 int dfs(int u, int pre)
 71 {
 72     if(dp[u]!=-1) return dp[u];
 73     dp[u] = num[u];
 74     for(int i = head0[u]; i!=-1; i = edge0[i].next)
 75     {
 76         int v = edge0[i].to;
 77         if(v==pre) continue;
 78         dp[u] = max(dp[u], num[u]+dfs(v, u));
 79     }
 80     return dp[u];
 81 }
 82 
 83 void init()
 84 {
 85     tot = tot0 = 0;
 86     memset(head, -1, sizeof(head));
 87     memset(head0, -1, sizeof(head0));
 88 
 89     Index = top = 0;
 90     memset(dfn, 0, sizeof(dfn));
 91     memset(low, 0, sizeof(low));
 92     memset(instack, 0, sizeof(instack));
 93 
 94     scc = 0;
 95     memset(num, 0, sizeof(num));
 96     memset(dp, -1, sizeof(dp));
 97 }
 98 
 99 int main()
100 {
101     int n, m, T;
102     scanf("%d", &T);
103     while(T--)
104     {
105         scanf("%d%d", &n, &m);
106         init();
107         for(int i = 1; i<=m; i++)
108         {
109             int u, v;
110             scanf("%d%d", &u, &v);
111             addedge(u, v, edge, head, tot);
112         }
113 
114         for(int i = 1; i<=n; i++)
115             if(!dfn[i])
116                 Tarjan(i);
117 
118         for(int u = 1; u<=n; u++)   //重建建图
119         for(int i = head[u]; i!=-1; i = edge[i].next)
120         {
121             int tmpu = belong[u];
122             int tmpv = belong[edge[i].to];
123             if(tmpu!=tmpv)
124                 addedge(tmpu, tmpv, edge0, head0, tot0);
125         }
126 
127         int ans = 0;
128         for(int i = 1; i<=scc; i++)
129             if(dp[i]==-1)
130                 ans = max(ans, dfs(i, i));
131 
132         printf("%d\n", ans);
133     }
134 }
View Code

 

代码二:

技术分享
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 #define ms(a,b) memset((a),(b),sizeof((a)))
 13 using namespace std;
 14 typedef long long LL;
 15 const double EPS = 1e-8;
 16 const int INF = 2e9;
 17 const int MAXM = 5e4+10;
 18 const int MAXN = 1e3+10;
 19 
 20 struct Edge
 21 {
 22     int to, next;
 23 }edge[MAXM];   //edge为初始图, edge0为重建图
 24 int tot, head[MAXN];
 25 vector<int>g[MAXN];
 26 
 27 int Index, dfn[MAXN], low[MAXN];
 28 int top, Stack[MAXN], instack[MAXN];
 29 int scc, belong[MAXN], num[MAXN];
 30 int dp[MAXN];
 31 
 32 void addedge(int u, int v)
 33 {
 34     edge[tot].to = v;
 35     edge[tot].next = head[u];
 36     head[u] = tot++;
 37 }
 38 
 39 void Tarjan(int u)
 40 {
 41     dfn[u] = low[u] = ++Index;
 42     Stack[top++] = u;
 43     instack[u] = true;
 44     for(int i = head[u]; i!=-1; i = edge[i].next)
 45     {
 46         int v = edge[i].to;
 47         if(!dfn[v])
 48         {
 49             Tarjan(v);
 50             low[u] = min(low[u], low[v]);
 51         }
 52         else if(instack[v])
 53             low[u] = min(low[u], dfn[v]);
 54     }
 55 
 56     if(dfn[u]==low[u])
 57     {
 58         int v;
 59         scc++;
 60         do
 61         {
 62             v = Stack[--top];
 63             instack[v] = false;
 64             belong[v] = scc;
 65             num[scc]++;
 66         }while(v!=u);
 67     }
 68 }
 69 
 70 int dfs(int u, int pre)
 71 {
 72     if(dp[u]!=-1) return dp[u];
 73     dp[u] = num[u];
 74     for(int i = 0; i<g[u].size(); i++)
 75     {
 76         int v = g[u][i];
 77         if(v==pre) continue;
 78         dp[u] = max(dp[u], num[u]+dfs(v, u));
 79     }
 80     return dp[u];
 81 }
 82 
 83 void init(int n)
 84 {
 85     tot = 0;
 86     memset(head, -1, sizeof(head));
 87 
 88     Index = top = 0;
 89     memset(dfn, 0, sizeof(dfn));
 90     memset(low, 0, sizeof(low));
 91     memset(instack, 0, sizeof(instack));
 92 
 93     scc = 0;
 94     memset(num, 0, sizeof(num));
 95     memset(dp, -1, sizeof(dp));
 96     for(int i = 1; i<=n; i++)
 97         g[i].clear();
 98 }
 99 
100 int main()
101 {
102     int n, m, T;
103     scanf("%d", &T);
104     while(T--)
105     {
106         scanf("%d%d", &n, &m);
107         init(n);
108         for(int i = 1; i<=m; i++)
109         {
110             int u, v;
111             scanf("%d%d", &u, &v);
112             addedge(u, v);
113         }
114 
115         for(int i = 1; i<=n; i++)
116             if(!dfn[i])
117                 Tarjan(i);
118 
119         for(int u = 1; u<=n; u++)   //重建建图
120         for(int i = head[u]; i!=-1; i = edge[i].next)
121         {
122             int tmpu = belong[u];
123             int tmpv = belong[edge[i].to];
124             if(tmpu!=tmpv)
125                 g[tmpu].push_back(tmpv);
126         }
127 
128         int ans = 0;
129         for(int i = 1; i<=scc; i++)
130             if(dp[i]==-1)
131                 ans = max(ans, dfs(i, i));
132 
133         printf("%d\n", ans);
134     }
135 }
View Code

 

代码三:

技术分享
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <queue>
  8 #include <stack>
  9 #include <map>
 10 #include <string>
 11 #include <set>
 12 #define ms(a,b) memset((a),(b),sizeof((a)))
 13 using namespace std;
 14 typedef long long LL;
 15 const double EPS = 1e-8;
 16 const int INF = 2e9;
 17 const int MAXN = 1e3+10;
 18 
 19 vector<int>G[MAXN], g[MAXN];
 20 
 21 int Index, dfn[MAXN], low[MAXN];
 22 int top, Stack[MAXN], instack[MAXN];
 23 int scc, belong[MAXN], num[MAXN];
 24 int dp[MAXN];
 25 
 26 void Tarjan(int u)
 27 {
 28     dfn[u] = low[u] = ++Index;
 29     Stack[top++] = u;
 30     instack[u] = true;
 31     for(int i = 0; i<G[u].size(); i++)
 32     {
 33         int v = G[u][i];
 34         if(!dfn[v])
 35         {
 36             Tarjan(v);
 37             low[u] = min(low[u], low[v]);
 38         }
 39         else if(instack[v])
 40             low[u] = min(low[u], dfn[v]);
 41     }
 42 
 43     if(dfn[u]==low[u])
 44     {
 45         int v;
 46         scc++;
 47         do
 48         {
 49             v = Stack[--top];
 50             instack[v] = false;
 51             belong[v] = scc;
 52             num[scc]++;
 53         }while(v!=u);
 54     }
 55 }
 56 
 57 int dfs(int u, int pre)
 58 {
 59     if(dp[u]!=-1) return dp[u];
 60     dp[u] = num[u];
 61     for(int i = 0; i<g[u].size(); i++)
 62     {
 63         int v = g[u][i];
 64         if(v==pre) continue;
 65         dp[u] = max(dp[u], num[u]+dfs(v, u));
 66     }
 67     return dp[u];
 68 }
 69 
 70 void init(int n)
 71 {
 72     Index = top = 0;
 73     memset(dfn, 0, sizeof(dfn));
 74     memset(low, 0, sizeof(low));
 75     memset(instack, 0, sizeof(instack));
 76 
 77     scc = 0;
 78     memset(num, 0, sizeof(num));
 79     memset(dp, -1, sizeof(dp));
 80     for(int i = 1; i<=n; i++)
 81     {
 82         G[i].clear();
 83         g[i].clear();
 84     }
 85 }
 86 
 87 int main()
 88 {
 89     int n, m, T;
 90     scanf("%d", &T);
 91     while(T--)
 92     {
 93         scanf("%d%d", &n, &m);
 94         init(n);
 95         for(int i = 1; i<=m; i++)
 96         {
 97             int u, v;
 98             scanf("%d%d", &u, &v);
 99             G[u].push_back(v);
100         }
101 
102         for(int i = 1; i<=n; i++)
103             if(!dfn[i])
104                 Tarjan(i);
105 
106         for(int u = 1; u<=n; u++)   //重建建图
107         for(int i = 0; i<G[u].size(); i++)
108         {
109             int tmpu = belong[u];
110             int tmpv = belong[G[u][i]];
111             if(tmpu!=tmpv)
112                 g[tmpu].push_back(tmpv);
113         }
114 
115         int ans = 0;
116         for(int i = 1; i<=scc; i++)
117             if(dp[i]==-1)
118                 ans = max(ans, dfs(i, i));
119 
120         printf("%d\n", ans);
121     }
122 }
View Code

 

UVA11324 The Largest Clique —— 强连通分量 + 缩点 + DP

标签:turn   题目   false   names   ack   memset   mes   scan   log   

原文地址:http://www.cnblogs.com/DOLFAMINGO/p/7820041.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!