您的位置:首页 > 其它

poj 3140 简单的树的应用

2012-07-21 11:06 183 查看
首先要说的是,做这个题目是被骗了,网上搜的时候,说是树型动态规划,结果看完题目后,觉得很简单,根本和动态规划没半点关系,以为是理解错误了,又读了几遍题目,结果还是和原来理解的一样,于是就想着:如果是做比赛,肯定是要按照我的思路写的。于是就想先写一下吧,错就错了,只当联联手,当写完后,提交,结果TMD 1A了,让我很郁闷,从看题目到现在,耽误我一个小时啊!哎、、算了吧,还是写个解题报告吧!就当是为了增加那么一点点的访问量。。。。。。

题目:给你一颗树,每个节点有权值,然后让你去掉一条边成为两颗树,使满足两颗树的权值差最小,把最小值输出。这个题目根本没有一点卡人的地方。唯一要注意的地方是一切用long long,并且那个abs不要用库函数,自己写,因为,那个库abs不支持long long。最后看了一下谈论区,好多都是因为这个WA了好久。没了,简单吧!!!!!

解题思路:增加0为根节点,然后0只有一个孩子就是1,与1连的是1的孩子,以此类推,然后就得到一颗树了。用每个节点储存它所有孩子的值,从0递归一下可以了。然后就从0递归,依次删除一个边i,求point[0]-2*pont[i]的最小值就可以了!

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;
#define N 100005
#define M 1000000000000000000
vector<int>tree
;
int num,edge;
long long point
,ans;
bool de
;
long long min(long long a,long long b)
{
return a>b?b:a;
}
long long abs(long long a)
{
return a>0?a:(-a);
}
void init()
{
int i,x,y;
memset(de,true,sizeof(de));
for(i=1;i<=num;i++)
{
scanf("%lld",&point[i]);
tree[i].clear();
}
for(i=1;i<=edge;i++)
{
scanf("%d%d",&x,&y);
tree[x].push_back(y);   tree[y].push_back(x);
}
}
long long dfs(int key)
{
de[key]=false;
vector <int>::iterator p=tree[key].begin();
while(p!=tree[key].end())
{
if(de[*p])
point[key]+=dfs(*p);
p++;
}
return point[key];
}
void fun(int key)
{
de[key]=false;
vector <int>::iterator p=tree[key].begin();
while(p!=tree[key].end())
{
if(de[*p])
{
ans=min(ans,abs(point[0]-2*point[*p]));
fun(*p);
}
p++;
}
}
int main()
{
//freopen("/home/acm/JPY/input.txt","r",stdin);
tree[0].push_back(1);
int cas=1;
while(cin>>num>>edge&&(num||edge))
{
init();
if(num==0)
{
cout<<"0"<<endl;
continue;
}
point[0]=dfs(1);        ans=M;
memset(de,true,sizeof(de));        fun(0);
printf("Case %d: %lld\n",cas++,ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: