UVA 11324 The Largest Clique (强连通分量缩点,图DP)

题目:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299

题意:

给你一个有向图,求一个点集合的最大大小,使得此点集合中对于任意点对(u,v),有从u到v或者从v到u的边

方法:

先找强连通分量缩点,每个强连通分量显然满足条件,然后在缩点后的图中找到一条权值最大的路径,权值为此路径的点权之和,点权为这个强连通分量的点数

1 int dp[maxn];
2 int dfs(int u)
3 {
4     if (dp[u]) return dp[u];
5     int ret = 0;
6     for (int i = head[u]; ~i; i = edge[i].next)
7         ret = max(ret, dfs(edge[i].v));
8     return dp[u] = ret + node[u];
9 }

代码:

  1 /********************************************
  2 *ACM Solutions
  3 *
  4 *@Title:
  5 *@Version: 1.0
  6 *@Time: 2014-xx-xx
  7 *@Solution: http://www.cnblogs.com/xysmlx/p/xxxxxxx.html
  8 *
  9 *@Author: xysmlx(Lingxiao Ma)
 10 *@Blog: http://www.cnblogs.com/xysmlx
 11 *@EMail: xysmlx@163.com
 12 *
 13 *Copyright (C) 2011-2015 xysmlx(Lingxiao Ma)
 14 ********************************************/
 15 // #pragma comment(linker, "/STACK:102400000,102400000")
 16 #include <cstdio>
 17 #include <iostream>
 18 #include <cstring>
 19 #include <string>
 20 #include <cmath>
 21 #include <set>
 22 #include <list>
 23 #include <map>
 24 #include <iterator>
 25 #include <cstdlib>
 26 #include <vector>
 27 #include <queue>
 28 #include <ctime>
 29 #include <stack>
 30 #include <algorithm>
 31 #include <functional>
 32 using namespace std;
 33 typedef long long ll;
 34 #define pb push_back
 35 #define ROUND(x) round(x)
 36 #define FLOOR(x) floor(x)
 37 #define CEIL(x) ceil(x)
 38 const int maxn = 1010;
 39 const int maxm = 200010;
 40 const int inf = 0x3f3f3f3f;
 41 const ll inf64 = 0x3f3f3f3f3f3f3f3fLL;
 42 const double INF = 1e30;
 43 const double eps = 1e-6;
 44 int kase;
 45 int n, m;
 46 struct Edge
 47 {
 48     int u, v;
 49     int next;
 50     Edge(int _u, int _v, int _next): u(_u), v(_v), next(_next) {}
 51     Edge() {}
 52 } edge[maxm];
 53 int en;
 54 int head[maxn];
 55 int node[maxn];
 56 void addse(int u, int v)
 57 {
 58     edge[en] = Edge(u, v, head[u]);
 59     head[u] = en++;
 60 }
 61 struct SCC
 62 {
 63     Edge edge[maxm];
 64     int en;
 65     int head[maxn];
 66     int h[maxn];
 67     void addse(int u, int v)
 68     {
 69         edge[en] = Edge(u, v, head[u]);
 70         head[u] = en++;
 71     }
 72     void init()
 73     {
 74         memset(head, -1, sizeof(head));
 75         en = 0;
 76     }
 77     int sid[maxn];
 78     int mark[maxn], low[maxn];
 79     int check[maxn];
 80     int sstack[maxn], top;
 81     int dfn, ssn;
 82     int n, m;
 83     bool mtx[maxn][maxn];
 84     void dfs(int k)
 85     {
 86         int i, j;
 87         check[k] = 1;
 88         low[k] = mark[k] = dfn++;
 89         sstack[top++] = k;
 90         for (int i = head[k]; i != -1; i = edge[i].next)
 91         {
 92             int j = edge[i].v;
 93             if (mark[j] == 0)
 94             {
 95                 dfs(j);
 96                 low[k] = min(low[k], low[j]);
 97             }
 98             else if (check[j])
 99                 low[k] = min(low[k], mark[j]);
100         }
101         if (mark[k] == low[k])
102         {
103             while (sstack[--top] != k)
104             {
105                 check[sstack[top]] = 0;
106                 sid[sstack[top]] = ssn;
107             }
108             sid[k] = ssn;
109             check[k] = 0;
110             ++ssn;
111         }
112         return;
113     }
114     void tarjan()
115     {
116         ssn = 1;
117         dfn = 1;
118         top = 0;
119         memset(check, 0, sizeof(check));
120         memset(mark, 0, sizeof(mark));
121         for (int i = 0; i < n; ++i) if (mark[i] == 0) dfs(i);
122 
123         memset(h, 0, sizeof(h));
124         for (int i = 0; i < n; i++)
125             h[sid[i]]++;
126         memset(mtx, 0, sizeof(mtx));
127         for (int i = 0; i < en; i++)
128             mtx[sid[edge[i].u]][sid[edge[i].v]] = 1;
129     }
130 } scc;
131 
132 int dp[maxn];
133 int dfs(int u)
134 {
135     if (dp[u]) return dp[u];
136     int ret = 0;
137     for (int i = head[u]; ~i; i = edge[i].next)
138         ret = max(ret, dfs(edge[i].v));
139     return dp[u] = ret + node[u];
140 }
141 
142 void init()
143 {
144     kase++;
145     scc.init();
146     memset(head, -1, sizeof(head));
147     en = 0;
148     memset(dp, 0, sizeof(dp));
149 }
150 void input()
151 {
152     scanf("%d%d", &n, &m);
153     scc.n = n;
154     for (int i = 0; i < m; i++)
155     {
156         int u, v;
157         scanf("%d%d", &u, &v);
158         u--, v--;
159         scc.addse(u, v);
160     }
161 }
162 void debug()
163 {
164     //
165 }
166 void solve()
167 {
168     scc.tarjan();
169     n = scc.ssn;
170     for (int i = 1; i < scc.ssn; i++)
171     {
172         for (int j = 1; j < scc.ssn; j++)
173         {
174             if (i == j) continue;
175             if (scc.mtx[i][j])
176                 addse(i, j);
177         }
178     }
179     for (int i = 1; i < scc.ssn; i++)
180         node[i] = scc.h[i];
181     // for (int i = 1; i < scc.ssn; i++)
182     //     cout << node[i] << " ";
183     // cout << endl;
184     int ans = 0;
185     memset(dp, 0, sizeof(dp));
186     for (int i = 1; i < n; i++)
187     {
188         ans = max(ans, dfs(i));
189     }
190     printf("%d
", ans);
191 }
192 void output()
193 {
194     //
195 }
196 int main()
197 {
198     // 32-bit
199     // int size = 256 << 20; // 256MB
200     // char *p = (char *)malloc(size) + size;
201     // __asm__("movl %0, %%esp
" :: "r"(p));
202 
203     // 64-bit
204     // int size = 256 << 20; // 256MB
205     // char *p = (char *)malloc(size) + size;
206     // __asm__("movq %0, %%rsp
" :: "r"(p));
207 
208     // std::ios_base::sync_with_stdio(false);
209 #ifdef xysmlx
210     freopen("in.txt", "r", stdin);
211 #endif
212 
213     kase = 0;
214     int T;
215     scanf("%d", &T);
216     while (T--)
217     {
218         init();
219         input();
220         solve();
221         output();
222     }
223     return 0;
224 }
UVA 11324
原文地址:https://www.cnblogs.com/xysmlx/p/4057747.html