您的位置:首页 > 其它

多校北邮现场赛(bupt 196 cc on the tree 搜索叶结点间的最短路 DFS)

2011-07-18 22:40 561 查看
比赛的时候只想到了算法,但是没敲,队友很蛋疼的拿SPFA去求叶间的最短路,树上叶结点间的路径是唯一的,求出来就是最短的,居然能用SPFA敲,必然TLE啊,我很无语。。。
本题我用的算法就是DFS 任举一个非叶结点为根,这里我用的是序号最小的非叶结点,然后从根向各结点扩展搜索,到叶停止返回一个0和INF,每个结点返回最小和次小路径的值,因为2叶间最小路径必是某一结点到2叶的最小和次小值相加,当然结点数为2的要特殊处理下
#include <cstdio>
#include <string.h>
#define min(a,b) (a)>(b)?(b):(a)
#define swap(a,b) if((a)>(b)){int (t)=(a);(a)=(b);(b)=(t);}
const int maxn=10010;
const int inf=1<<29;
int min1[maxn];
int min2[maxn];
int deg[maxn];
bool vis [maxn];
struct node
{
int v,w;
node *next;
node (int a,int b):v(a),w(b){};
};
node * List[maxn];

void dfs (const int &u)
{
int tmp1=inf,tmp2=inf,i,v,w,t,t1,t2;
vis[u]=true;
if(deg[u]==1){ min1[u]=0; return ;}
node *p=List[u];
for ( ; p!=NULL ; p=p->next)
{
v=p->v;
w=p->w;
//printf("%d %d\n",v+1,u+1);
if(!vis[v])
{
dfs(v);
t1=w+min1[v];
t2=w+min2[v];
//printf("%d %d %d %d\n",t1,t2 ,tmp1 ,tmp2);
swap(tmp1,t1);
swap(tmp1,t2);
swap(tmp1,tmp2);
swap(tmp2,t1);
swap(tmp2,t2);
}
}
min1[u]=tmp1;
min2[u]=tmp2;
}

int main ()
{
int n,i,j,u,v,w;
//freopen("in.txt","r",stdin);
while (~scanf("%d",&n)&&n)
{
node *tmp1,*tmp2;
if(n==2){scanf("%d%d%d",&u,&v,&w);printf("%d\n",w);continue;}
for (i=0 ; i<n ; i++)
{
List[i]=NULL;
min1[i]=min2[i]=inf;
deg[i]=0;
vis[i]=false;
}
for (i=0 ; i<n-1 ; ++i)
{
scanf("%d%d%d",&u,&v,&w);
u--,v--;
deg[u]++,deg[v]++;
tmp1=new node(v,w);
tmp1->next=NULL;
tmp2=new node(u,w);
tmp2->next=NULL;
List[u]==NULL?List[u]=tmp1:(tmp1->next=List[u],List[u]=tmp1);
List[v]==NULL?List[v]=tmp2:(tmp2->next=List[v],List[v]=tmp2);
}
/*for (i=0 ; i<n-1 ; i++)
for (node * p=List[i] ; p!=NULL ; p=p->next)
printf("%d: %d %d \n",i,p->v,p->w);*/
for (i=0 ; deg[u=i]<2 ; ++i);
//printf("%d\n",u+1);//找一个序号最小的非叶节点
dfs(u);
int ans=inf;
for (i=0 ; i<n ; ++i)
ans=min(ans,min1[i]+min2[i]);
//for (i=0 ; i<n ; ++i)
//printf("%d %d\n",min1[i],min2[i]);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: