UVA - 1218 Perfect Service(트리 dp)
8876 단어 dp
제목
n대의 컴퓨터가 있는데 서로 뿌리가 없는 방식으로 연결된다. 현재 그 중 일부 컴퓨터를 서버로 하고 모든 컴퓨터가 반드시 연결되어야 하며 서버(서버로 하는 컴퓨터 제외)만 연결할 수 있도록 요구하며 최소한 몇 대의 컴퓨터를 서버로 해야 하는지를 요구한다.
생각
전형적인 트리 dp 문제, 그러면 우리는 모델을 세웁니다.d(u,0):u는 서버입니다. 아이가 서버인지 아닌지는 모두 d(u,1):u는 서버가 아닙니다. u의 아버지는 서버입니다. u의 아이는 서버가 될 수 없습니다. d(u,2):u는 서버가 아닙니다. u의 아버지는 서버가 아닙니다. u의 아이는 반드시 있어야 하고 하나만이 서버입니다.
그렇다면 명백한 d(u,0)= 1+Sum(Min(d(v,1), d(v,0))|v는 u의 아이 d(u,1)=Sum(d,2)d(u,2)는 좀 복잡하다. 한 아이만 서버이기 때문에 모든 아이가 서버인 상황을 두루 겪어야 한다. 한 바퀴 한 바퀴는 다른 모든 아이를 동시에 계산해야 하고 O(N^2)의 시간이 필요하다.분명히 이렇게 하면 여러 가지 중복 계산 상황이 있을 것이다. 당연히 기억화하여 속도를 높일 수 있지만, 더 빠른 기교가 하나 있다. 왜냐하면 d(u,1)와 d(u,2)의 유일한 차이점은 d(u,2)의 아이가 서버를 가지고 있기 때문이다. 그러면 우리는 d(u,2)=Min(u,1)-d(v,2)+d(v,0)|v는 u의 아이가 여전히 모든 아이를 서버로 하고 있으며, 매 라운드의 조작은 O(1)로 전체적으로 O(N)이다.
코드
ps: d(u,2)를 처음에 무한대로 설정하기 때문에 0x3f3f3f3f를 설치했는데 결과적으로 N으로 바꾸면 됩니다. 오랫동안 찾아서 문제를 찾았습니다. 이 wrong으로 인해 여러 번 문제가 생겼지만 왜 wrong인지 모르겠습니다. 원인을 아는 도우들은 아낌없는 조언을 해 주십시오.
첫 번째 a의 코드
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
const int N = 10009;
vector<int> g[N];
int dp[N][3];
void dfs(int u, int fa)
{
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i] != fa)
dfs(g[u][i], u);
}
dp[u][0] = 1;
dp[u][1] = 0;
dp[u][2] = N;
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i] != fa)
{
dp[u][0] += min(dp[g[u][i]][0], dp[g[u][i]][1]);
dp[u][1] += dp[g[u][i]][2];
}
}
bool f = true;
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i] != fa)
{
f = false;
dp[u][2] = min(dp[u][2], dp[u][1]+dp[g[u][i]][0]-dp[g[u][i]][2]);
}
}
}
int main()
{
int n;
while(cin>>n)
{
memset(dp, -1, sizeof(dp));
int a, b;
for(int i=1; i<n; i++)
{
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1, -1);
cout<<min(dp[1][0], dp[1][2])<<endl;
cin>>a;
if(a == -1)
break;
for(int i=1; i<=n; i++)
g[i].clear();
}
return 0;
}
대신코드를 참관한 후 수정한 간략판
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
const int N = 10009;
vector<int> g[N];
int dp[N][3];
void dfs(int u, int fa)
{
dp[u][0] = 1;
dp[u][1] = 0;
dp[u][2] = N;
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i] != fa)
{
dfs(g[u][i], u);
dp[u][0] += min(dp[g[u][i]][0], dp[g[u][i]][1]);
dp[u][1] += dp[g[u][i]][2];
}
}
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i] != fa)
dp[u][2] = min(dp[u][2], dp[u][1]+dp[g[u][i]][0]-dp[g[u][i]][2]);
}
}
int main()
{
int n;
while(cin>>n)
{
int a, b;
for(int i=1; i<n; i++)
{
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1, -1);
cout<<min(dp[1][0], dp[1][2])<<endl;
cin>>a;
if(a == -1)
break;
for(int i=1; i<=n; i++)
g[i].clear();
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【경쟁 프로 전형적인 90문】008의 해설(python)의 해설 기사입니다. 해설의 이미지를 봐도 모르는 (이해력이 부족한) 것이 많이 있었으므로, 나중에 다시 풀었을 때에 확인할 수 있도록 정리했습니다. ※순차적으로, 모든 문제의 해설 기사를 들어갈 예정입니다. 문자열...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.