제목 링크:https://vjudge.net/problem/UVA-11324
제목: 지향도 G를 주고 노드 수가 가장 큰 결점 집합을 구하여 이 결점은 임의의 두 결점 u와 v를 집중하여 만족시킨다. u는 v에 도달할 수 있거나 v는 u에 도달할 수 있다(또는 u와 v는 서로 도달할 수 있다)
사고방식: 먼저 그림의 강연통 분량을 구하고 그 수축점을 scc그림으로 얻어 각 scc결점의 권한값은 그의 노드수이다.문제는 DAG 그림을 보여주고 각 점의 값을 알고 가장 큰 값을 구하는 경로로 바뀌었다.dp로 해답을 구할 수 있다.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define fin(a) freopen("a.txt","r",stdin)
#define fout(a) freopen("a.txt","w",stdout)
using namespace std;
const int maxn = 1000 + 10;
stack S;
vector G[maxn], G2[maxn];
int n, m;
int con[maxn][maxn], dp[maxn], sccno[maxn], pre[maxn], low[maxn], val[maxn], scc_cnt, scc_clock;
void input_Edge() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) G[i].clear();
for(int i = 1; i <= m; i++) {
int x, y;
scanf("%d%d", &x, &y);
G[x].push_back(y);
}
}
void dfs(int u) {
pre[u] = low[u] = ++scc_clock;
S.push(u);
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(!pre[v]) {
dfs(v);
low[u] = min(low[u], low[v]);
}
else if(!sccno[v]) {
low[u] = min(low[u], pre[v]);
}
}
if(low[u] == pre[u]) {
++scc_cnt;
for(;;) {
int x = S.top(); S.pop();
sccno[x] = scc_cnt;
val[scc_cnt]++;
if(x == u) break;
}
}
}
void get_scc() {
while(!S.empty()) S.pop();
memset(sccno, 0, sizeof sccno);
memset(pre, 0, sizeof pre);
memset(low, 0, sizeof low);
memset(val, 0, sizeof val);
scc_cnt = scc_clock = 0;
for(int i = 1; i <= n; i++)
if(!pre[i]) dfs(i);
}
void get_new() {
memset(con, 0, sizeof con);
for(int i = 1; i <= n; i++) G2[i].clear();
for(int u = 1; u <= n; u++)
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
int a = sccno[u], b = sccno[v];
if(a == b || con[a][b]) continue;
con[a][b] = 1;
G2[a].push_back(b);
}
}
int d(int u) {
if(G2[u].size() == 0) return val[u];
int& ans = dp[u];
if(ans > 0) return ans;
for(int i = 0; i < G2[u].size(); i++)
ans = max(ans, val[u] + d(G2[u][i]));
return ans;
}
int solve() {
memset(dp, 0, sizeof dp);
int ans = 0;
for(int i = 1; i <= scc_cnt; i++)
ans = max(ans, d(i));
return ans;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
input_Edge();
get_scc();
get_new();
printf("%d ", solve());
}
return 0;
}
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
UVa 548 트리
제목: 중순과 후순 서열을 제시하고 뿌리에서 잎사귀 결점까지의 경로와 값이 가장 작은 잎사귀 결점을 구한다.값과 같으면 잎사귀 결점 값이 비교적 작은 것을 선택하십시오.
사고방식: 중순과 후순 서열로 돌아가며 두 갈...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.