先强连通缩点求出DAG图,求最大权值的时候,因为存在重边,也存在一个点从多条路径到达终点的情况。。所以要建反图,找入度为0的点DFS求出最大权。。这样用DFS就可以很好的解决上面两个问题。。。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 5005 #define maxm 30005 #define eps 1e-10 #define mod 1000000009 #define INF 99999999 #define lowbit(x) (x&(-x)) //#define lson o<<1, L, mid //#define rson o<<1 | 1, mid+1, R typedef long long LL; //typedef int LL; using namespace std; int H[maxn], NEXT[maxm], V[maxm]; int h[maxn], next[maxm], v[maxm]; int dfn[maxn], low[maxn], id[maxn]; int in[maxn], ins[maxn], p[maxn]; int w[maxn], res[maxn], vis[maxn]; int n, m, scc_cnt, top, mx, ans, ans_cnt, mmx; vector<int> vec[maxn]; stack<int> s; void init(void) { top = scc_cnt = ans_cnt = mx = ans = 0; memset(h, -1, sizeof h); memset(H, -1, sizeof H); memset(w, 0, sizeof w); memset(in, 0, sizeof in); memset(ins, 0, sizeof ins); memset(dfn, 0, sizeof dfn); for(int i = 0; i < maxn; i++) vec[i].clear(); } void read(void) { int a, b, cnt = 0; scanf("%d%d", &n, &m); while(m--) { scanf("%d%d", &a, &b); a++, b++; NEXT[cnt] = H[a], H[a] = cnt, V[cnt] = b, cnt++; } } void tarjan(int u) { dfn[u] = low[u] = ++top; s.push(u), ins[u] = 1; for(int e = H[u]; ~e; e = NEXT[e]) if(!dfn[V[e]]) { tarjan(V[e]); low[u] = min(low[u], low[V[e]]); } else if(ins[V[e]]) low[u] = min(low[u], dfn[V[e]]); if(dfn[u] == low[u]) { int tmp = s.top(); s.pop(), ins[tmp] = 0; ++scc_cnt; while(tmp != u) { id[tmp] = scc_cnt; tmp = s.top(); s.pop(); ins[tmp] = 0; } id[tmp] = scc_cnt; } } void narrow(void) { int cnt = 0; for(int i = 1; i <= n; i++) for(int e = H[i]; ~e; e = NEXT[e]) next[cnt] = h[id[V[e]]], h[id[V[e]]] = cnt, v[cnt] = id[i], cnt++; } void dfs(int u) { if(vis[u]) return; vis[u] = 1; mx += w[u]; if(mx > mmx) mmx = mx; for(int e = h[u]; ~e; e = next[e]) dfs(v[e]); //mx -= w[u]; } void debug(void) { printf("FD %d\n", ans_cnt); for(int i = 0; i < ans_cnt; i++) printf("AAA %d BBB\n", p[i]); } void work(int CASE) { int i, num = 0; for(i = 1; i <= n; i++) if(!dfn[i]) tarjan(i); narrow(); for(i = 1; i <= scc_cnt; i++) for(int e = h[i]; ~e; e = next[e]) if(v[e] != i) in[v[e]]++; for(i = 1; i <= n; i++) w[id[i]]++; for(i = 1; i <= n; i++) vec[id[i]].push_back(i); for(i = 1; i <= scc_cnt; i++) if(!in[i]) { memset(vis, 0, sizeof vis); mmx = mx = 0; dfs(i); if(mmx == ans) p[ans_cnt++] = i; if(mmx > ans) ans_cnt = 0, p[ans_cnt++] = i, ans = mmx; } for(i = 0; i < ans_cnt; i++) { int d = vec[p[i]].size(); for(int j = 0; j < d; j++) res[num++] = vec[p[i]][j]; } sort(res, res+num); printf("Case %d: %d\n", CASE, --ans); if(num) printf("%d", --res[0]); for(i = 1; i < num; i++) printf(" %d", --res[i]); printf("\n"); } int main(void) { int _, __; while(scanf("%d", &_)!=EOF) { __ = 0; while(_--) { init(); read(); work(++__); } } return 0; }