P3931 SAC E#1 - 一道难题 Tree
2017-10-07
题目背景
冴月麟和魏潇承是好朋友。
题目描述
冴月麟为了守护幻想乡,而制造了幻想乡的倒影,将真实的幻想乡封印了。任何人都无法进入真实的幻想乡了,但是她给前来救她的魏潇承留了一个线索。
她设置了一棵树(有根)。树的每一条边上具有割掉该边的代价。
魏潇承需要计算出割开这棵树的最小代价,这就是冴月麟和魏潇承约定的小秘密。
帮帮魏潇承吧。
注:所谓割开一棵有根树,就是删除若干条边,使得任何任何叶子节点和根节点不连通。
输入输出格式
输入格式:输入第一行两个整数n,S表示树的节点个数和根。
接下来n-1行每行三个整数a、b、c,表示a、b之间有一条代价为c的边。
输出格式:输出包含一行,一个整数,表示所求最小代价。
输入输出样例
输入样例#1:
4 1 1 2 1 1 3 1 1 4 1
输出样例#1:
3
输入样例#2:
4 1 1 2 3 2 3 1 3 4 2
输出样例#2:
1
说明
对于20%的数据,n <= 10
对于50%的数据,n <= 1000
对于100%的数据,n <= 100000
这个题太可怕了,还是普及组的题目...x
dp比暴力还好想.暴力是我过后看题解后才发现可以这样做的x
我们用dp[i]表示让i以及以i为根节点的子树合法所要的最小贡献.
特殊的,每一个叶子节点的权值为INT
暴力转移qwq
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #define ll long long using namespace std; const int maxn=100000+2333; const int INT=1e9+7; inline int read(){ int an=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();} return an*f; } int f[maxn],cnt; int dp[maxn]; bool vis[maxn]; struct saber{ int nex,to,wi; }b[maxn<<1]; int root,n,in[maxn]; inline void add(int x,int y,int z){ cnt++; b[cnt].to=y; b[cnt].nex=f[x]; b[cnt].wi=z; f[x]=cnt; } void dfs(int x){ vis[x]=1; if(in[x]!=1)dp[x]=0; for(int i=f[x];i;i=b[i].nex){ int v=b[i].to; if(!vis[v]){ dfs(v); dp[x]+=min(dp[v],b[i].wi); } } } int main(){ n=read();root=read(); for(int i=1;i<n;i++){ int x=read(),y=read(),z=read(); add(x,y,z); add(y,x,z); in[x]++;in[y]++; } for(int i=1;i<=n;++i)dp[i]=INT; dp[root]=0; dfs(root); cout<<dp[root]; return 0; }
by:s_a_b_e_r