FOJ 2185 树的路径覆盖 (图)

来源:互联网 发布:js position fixed 编辑:程序博客网 时间:2024/06/05 05:41

题目:http://acm.fzu.edu.cn/problem.php?pid=2185

题意:n个点n-1条边, 用最少的路径去覆盖所有的边, 求(1)允许边被重复覆盖, (2)不允许边被重复覆盖.

分析:(1)可重复覆盖的话,总会由叶子节点走到另外一个叶子节点,路径数就是结子节点的数目n/2向上取整,n==1时特判。(2)和(1)一样由叶子节点走到叶子节点,不过走过的线路要删掉,同时会产生新的叶子节点,用一个队列存放叶子节点,然后直接由叶子节点推到另外一个叶子节点.

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <queue>using namespace std;#define MAXN 100005queue <int > leaf;struct node1{int head;int count;};struct node2{int value;int next;};struct tree{node1 Table[MAXN];node2 List[1000000];int cnt;void Clear(){cnt=0;for(int i=0;i<MAXN;i++){Table[i].count=0;Table[i].head=-1;}}void Insert(int a,int b){List[cnt].value=b;List[cnt].next=Table[a].head;Table[a].head=cnt;Table[a].count++;cnt++;List[cnt].value=a;List[cnt].next=Table[b].head;Table[b].head=cnt;Table[b].count++;cnt++;}void Delete(int a,int b){int pos,per=-1;pos=Table[a].head;while(List[pos].value!=b){per=pos;pos=List[pos].next;}if(per==-1)Table[a].head=List[pos].next;elseList[per].next=List[pos].next;Table[a].count--;per=-1;pos=Table[b].head;while(List[pos].value!=a){per=pos;pos=List[pos].next;}if(per==-1)Table[b].head=List[pos].next;elseList[per].next=List[pos].next;Table[b].count--;}}T;int Find(){while(!leaf.empty() && T.Table[leaf.front()].count!=1)leaf.pop();if(leaf.empty())return -1;elsereturn leaf.front();}int main(){int n,i,j,x,cnt,ans,cur,pos1,pos2,temp;int Tcase;scanf("%d\n",&Tcase); while(Tcase--){scanf("%d",&n);ans=cnt=0;T.Clear();while(!leaf.empty())leaf.pop();for(i=1;i<=n-1;i++){scanf("%d",&x);T.Insert(x,i);}//for(i=0;i<=n-1;i++)//{//int temp=T.Table[i].head;//printf("%d count(%d):",i,T.Table[i].count);//while(temp!=-1)//{//printf("%d ",T.List[temp].value);//temp=T.List[temp].next;//}//printf("\n");//}for(i=0;i<=n-1;i++){if(T.Table[i].count==1){cnt++;leaf.push(i);}}while((cur=Find())!=-1){ans++;while(1){pos1=cur;temp=T.Table[pos1].head;pos2=T.List[temp].value;T.Delete(pos1,pos2);cur=pos2;if(T.Table[pos1].count==1)leaf.push(pos1);if(T.Table[pos2].count==1)leaf.push(pos2);if(T.Table[cur].count==0)break;}}if(cnt==1)printf("0 %d\n",ans);elseprintf("%d %d\n",(cnt+2-1)/2,ans); }return 0;}


0 0