小G有一个大树
解题思路
AC代码
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e6+10;
int sum=inf,node,n,w[N];
vector<int> tree[N];
void dfs(int x,int fa) {
int maxx=0;
w[x]=1;
for(int i=0;i<tree[x].size();i++) {
int tx=tree[x][i];
if(tx==fa) continue;
dfs(tx,x);
w[x]+=w[tx];
maxx=max(maxx,w[tx]);
}
maxx=max(maxx,n-w[x]);
if(maxx<sum) {
sum=maxx;
node=x;
}
else if(maxx==sum) {
node=min(x,node);
}
}
int main(){
while(cin>>n) {
sum=inf;node=0;
memset(w,0,sizeof w);
for(int i=1;i<=n;i++) tree[i].clear();
for(int i=1;i<n;i++) {
int u,v;
cin>>u>>v;
tree[u].push_back(v);
tree[v].push_back(u);
}
dfs(1,0);
cout<<node<<' '<<sum<<endl;
}
} Rinne Loves Edges
解题思路
坑人的地方就是最后的数据说明:M=N-1,就是棵树!
定义好dp的含义才是最重要的。
dp[i]表示以i为根节点的子树,不存在1度结点与之相连通,所需要的最小花费。
转移方程:dp[x] = ∑(min(dp[tx], cost(x,tx))) 其中tx为x的子节点。
AC代码
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e5+100;
struct node{
int to,cost;
};
vector<node> g[N];
int dp[N],n,m,s;
void dfs(int x,int fa) {
int sum=0;
dp[x]=0;
for(int i=0;i<g[x].size();i++) {
if(fa==g[x][i].to) continue;
dfs(g[x][i].to,x);
if(dp[g[x][i].to]==0) dp[g[x][i].to]=inf;//注意!
dp[x]+=min(dp[g[x][i].to],g[x][i].cost);
}
}
int main(){
cin>>n>>m>>s;
for(int i=1;i<=m;i++) {
int u,v,w;cin>>u>>v>>w;
node tmp;tmp.to=v;tmp.cost=w;
//用结构体的思考过程(比较好想):如何存花费,用二维数组明显开不下,那就用二维vector,虽然能存下了,但是dfs的时候对应儿子结点,最后为了将结点与花费联系起来,就放在了结构体vector里了
g[u].pb(tmp);
tmp.to=u;
g[v].pb(tmp);
}
dfs(s,0);
cout<<dp[s]<<endl;
}
京公网安备 11010502036488号