UVA

给定一个图,求一个节点数目最多的团,对于其中任意两个节点u,v至少存在一条这样的路径使得u到v,或者v到u。

分析: 先求出强连通分量,然后缩点,构成一个scc图,然后求一条最长的路,每个节点的权重即为该强连通分量的节点数目,由于是DAG, 所以可以用dp或者spfa,一开始用记忆化搜索竟然TLE,想也想不通,后来改成spfa,以0为起点,然后求出距离0的最大距离。

spfa:

  1 #include <iostream>
  2 #include <sstream>
  3 #include <cstdio>
  4 #include <climits>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <string>
  8 #include <stack>
  9 #include <map>
 10 #include <cmath>
 11 #include <vector>
 12 #include <queue>
 13 #include <algorithm>
 14 #define esp 1e-6
 15 #define pi acos(-1.0)
 16 #define pb push_back
 17 #define mp(a, b) make_pair((a), (b))
 18 #define in  freopen("in.txt", "r", stdin);
 19 #define out freopen("out.txt", "w", stdout);
 20 #define print(a) printf("%d
",(a));
 21 #define bug puts("********))))))");
 22 #define stop  system("pause");
 23 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
 24 
 25 #define inf 0x0f0f0f0f
 26 
 27 using namespace std;
 28 typedef long long  LL;
 29 typedef vector<int> VI;
 30 typedef pair<int, int> pii;
 31 typedef vector<pii,int> VII;
 32 typedef vector<int>:: iterator IT;
 33 const int maxn = 5000;
 34 int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
 35 int a[maxn], dp[maxn], dis[maxn], inq[maxn];
 36 VI g[maxn], G[maxn];
 37 stack<int> S;
 38 void dfs(int u)
 39 {
 40     S.push(u);
 41     lowlink[u] = pre[u] = ++dfs_clock;
 42     for(int i = 0; i < g[u].size(); i++)
 43     {
 44         int  v = g[u][i];
 45         if(!pre[v])
 46         {
 47             dfs(v);
 48             lowlink[u] = min(lowlink[u], lowlink[v]);
 49         }
 50         else if(!sccno[v])
 51         {
 52             lowlink[u] = min(lowlink[u], pre[v]);
 53         }
 54     }
 55     int cnt= 0;
 56     if(lowlink[u] == pre[u])
 57     {
 58         scc_cnt++;
 59         for(;;)
 60         {
 61             int x = S.top();
 62             S.pop();
 63             cnt++;
 64             sccno[x] = scc_cnt;
 65             if(x ==  u)
 66             {
 67                 a[scc_cnt] = cnt;
 68                 break;
 69             }
 70         }
 71     }
 72 }
 73 void find_scc(int n)
 74 {
 75     memset(pre, 0, sizeof(pre));
 76     memset(sccno, 0, sizeof(sccno));
 77 
 78     dfs_clock = scc_cnt = 0;
 79     for(int i = 0; i < n; i++)
 80         if(!pre[i]) dfs(i);
 81 }
 82 void spfa(void)
 83 {
 84     memset(inq, 0, sizeof(inq));
 85     memset(dis, 0, sizeof(dis));
 86     queue<int> q;
 87     inq[0] = 1;
 88     q.push(0);
 89     while(!q.empty())
 90     {
 91         int u = q.front();
 92         q.pop();
 93         inq[u] = 0;
 94         for(int i = 0; i < G[u].size(); i++)
 95         {
 96             int v = G[u][i];
 97             if(dis[v] < dis[u] + a[v])
 98                 if(dis[v] = dis[u] + a[v], !inq[v])
 99                     inq[v] = 1, q.push(v);
100         }
101     }
102 }
103 int main(void)
104 {
105     int n, m;
106     int T;
107     for(int t = scanf("%d", &T); t <= T; t++)
108     {
109         for(int i = 0; i < maxn; i++)
110             g[i].clear(), G[i].clear();
111         scanf("%d%d", &n, &m);
112         memset(a, 0, sizeof(a));
113         while(m--)
114         {
115             int u, v;
116             scanf("%d%d", &u, &v);
117             u--, v--;
118             g[u].pb(v);
119         }
120         find_scc(n);
121         for(int u = 0; u < n; u++)
122             for(int i = 0; i < g[u].size(); i++)
123             {
124                 int v = g[u][i];
125                 if(sccno[v] != sccno[u])
126                     G[sccno[u]].pb(sccno[v]);
127             }
128         for(int i = 1; i <= scc_cnt; i++)
129             G[0].pb(i);
130         spfa();
131         int ans = 0;
132         for(int i = 1; i <= scc_cnt; i++)
133             ans = max(ans, dis[i]);
134         printf("%d
", ans);
135     }
136     return 0;
137 }
View Code

下面是dp代码,一开始用的邻接矩阵存储关系图,后来改成邻接表果断过了,以后要注意了,尽量用邻接表

  1 #include <iostream>
  2 #include <sstream>
  3 #include <cstdio>
  4 #include <climits>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <string>
  8 #include <stack>
  9 #include <map>
 10 #include <cmath>
 11 #include <vector>
 12 #include <queue>
 13 #include <algorithm>
 14 #define esp 1e-6
 15 #define pi acos(-1.0)
 16 #define pb push_back
 17 #define mp(a, b) make_pair((a), (b))
 18 #define in  freopen("in.txt", "r", stdin);
 19 #define out freopen("out.txt", "w", stdout);
 20 #define print(a) printf("%d
",(a));
 21 #define bug puts("********))))))");
 22 #define stop  system("pause");
 23 #define Rep(i, c) for(__typeof(c.end()) i = c.begin(); i != c.end(); i++)
 24 
 25 #define inf 0x0f0f0f0f
 26 
 27 using namespace std;
 28 typedef long long  LL;
 29 typedef vector<int> VI;
 30 typedef pair<int, int> pii;
 31 typedef vector<pii,int> VII;
 32 typedef vector<int>:: iterator IT;
 33 const int maxn = 5000;
 34 int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
 35 int a[maxn], dp[maxn], dis[maxn], inq[maxn];
 36 VI g[maxn], G[maxn];
 37 stack<int> S;
 38 void dfs(int u)
 39 {
 40     S.push(u);
 41     lowlink[u] = pre[u] = ++dfs_clock;
 42     for(int i = 0; i < g[u].size(); i++)
 43     {
 44         int  v = g[u][i];
 45         if(!pre[v])
 46         {
 47             dfs(v);
 48             lowlink[u] = min(lowlink[u], lowlink[v]);
 49         }
 50         else if(!sccno[v])
 51         {
 52             lowlink[u] = min(lowlink[u], pre[v]);
 53         }
 54     }
 55     int cnt= 0;
 56     if(lowlink[u] == pre[u])
 57     {
 58         scc_cnt++;
 59         for(;;)
 60         {
 61             int x = S.top();
 62             S.pop();
 63             cnt++;
 64             sccno[x] = scc_cnt;
 65             if(x ==  u)
 66             {
 67                 a[scc_cnt] = cnt;
 68                 break;
 69             }
 70         }
 71     }
 72 }
 73 void find_scc(int n)
 74 {
 75     memset(pre, 0, sizeof(pre));
 76     memset(sccno, 0, sizeof(sccno));
 77 
 78     dfs_clock = scc_cnt = 0;
 79     for(int i = 0; i < n; i++)
 80         if(!pre[i]) dfs(i);
 81 }
 82 void spfa(void)
 83 {
 84     memset(inq, 0, sizeof(inq));
 85     memset(dis, 0, sizeof(dis));
 86     queue<int> q;
 87     inq[0] = 1;
 88     q.push(0);
 89     while(!q.empty())
 90     {
 91         int u = q.front();
 92         q.pop();
 93         inq[u] = 0;
 94         for(int i = 0; i < G[u].size(); i++)
 95         {
 96             int v = G[u][i];
 97             if(dis[v] < dis[u] + a[v])
 98                 if(dis[v] = dis[u] + a[v], !inq[v])
 99                     inq[v] = 1, q.push(v);
100         }
101     }
102 }
103 int main(void)
104 {
105     int n, m;
106     int T;
107     for(int t = scanf("%d", &T); t <= T; t++)
108     {
109         for(int i = 0; i < maxn; i++)
110             g[i].clear(), G[i].clear();
111         scanf("%d%d", &n, &m);
112         memset(a, 0, sizeof(a));
113         while(m--)
114         {
115             int u, v;
116             scanf("%d%d", &u, &v);
117             u--, v--;
118             g[u].pb(v);
119         }
120         find_scc(n);
121         for(int u = 0; u < n; u++)
122             for(int i = 0; i < g[u].size(); i++)
123             {
124                 int v = g[u][i];
125                 if(sccno[v] != sccno[u])
126                     G[sccno[u]].pb(sccno[v]);
127             }
128         for(int i = 1; i <= scc_cnt; i++)
129             G[0].pb(i);
130         spfa();
131         int ans = 0;
132         for(int i = 1; i <= scc_cnt; i++)
133             ans = max(ans, dis[i]);
134         printf("%d
", ans);
135     }
136     return 0;
137 }
View Code
原文地址:https://www.cnblogs.com/rootial/p/3337805.html