UESTC 1717 Journey
来源:互联网 发布:统计学的数据分析实例 编辑:程序博客网 时间:2024/06/03 17:19
题意:给你一颗顶点数为n的树,然后再给出一条边,连接这棵树的两个顶点。然后有q条询问,每条询问给出两个点a、b,问从a-b走最后给出的边是否能节省路程,若能则输出节省的路程,若不能输出0。
思路:这道题我感觉自己想的比较麻烦,不知道有没有其他的算法。首先,由于这个图本来是棵树,加了一条边就形成了一个环,从a-b所走的路有两种情况:
①经过所给出的那条边
②不经过所给出的那条边
对于这个环上的点v,它的子树上的点要到这棵树以外的其他节点必须通过v,因此这个点子数上的所有点都相当于v。于是把所有的树叶一个一个删掉,最后会形成一个环。
问题就变成了在这个环上的的a点到b点经过给出的边所走的路程是否大于不经过所给出的那条边所走的路程。这两个路线用dfs搜一下就好,这里要注意经过所给出的那条边所走的路程有两种走法,只求出一种,然后环的长度减去这个长度就得到另外一种走法的路程了,然后取这两个数的较小的值就行了。
这题开始时没看到最后那个边是加上去的,题意也理解的不太对,写的十分蛋疼,还不对,改了好多遍,因此代码写的比较丑……
#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cstdio>#include<cmath>#include<map>#include<queue>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-8#define pi acos(-1.0)using namespace std;const int maxn=100000+10;int du[maxn],tidai[maxn],way1[maxn],way2[maxn];bool vis[maxn],treeleaf[maxn];int n;struct Dir{ int t,len;};vector<Dir>g[maxn];int len1,len2;void dfs(int u,int f,int c) //把环上点的子树都都用这个点替代{ int s=g[u].size(); int v; for(int i=0;i<s;++i) { v=g[u][i].t; if(treeleaf[v]&&v!=f) { tidai[v]=c; dfs(v,u,c); } }}void dfs2(int u,int f,int s,int e,int step){ int sn=g[u].size(); int v; for(int i=0;i<sn;++i) { v=g[u][i].t; if(v!=f&&!treeleaf[v]) { if(f==-1&&v==e) continue; if(v==s) { break; } step+=g[u][i].len; way1[v]=step; dfs2(v,u,s,e,step); step-=g[u][i].len; } }}void dfs3(int u,int f,int s,int e,int step){ int sn=g[u].size(); int v; for(int i=0;i<sn;++i) { v=g[u][i].t; if(v!=f&&!treeleaf[v]) { if(f==-1&&v!=e) continue; if(v==s) { way2[n+1]=step+g[u][i].len; break; } step+=g[u][i].len; way2[v]=step; dfs3(v,u,s,e,step); step-=g[u][i].len; } }}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int t,qt,tcase=0; scanf("%d",&t); while(t--) { tcase++; scanf("%d%d",&n,&qt); int a,b,c; Dir temp; for(int i=0;i<=n;++i) g[i].clear(); memset(du,0,sizeof(du)); memset(treeleaf,0,sizeof(treeleaf)); int x,y; for(int i=1;i<=n;++i) { scanf("%d%d%d",&a,&b,&c); temp.t=b;temp.len=c; g[a].push_back(temp); temp.t=a;temp.len=c; g[b].push_back(temp); du[a]++; du[b]++; if(i==n) { x=a; y=b; } } queue<int>q; for(int i=1;i<=n;++i) //找出所有的树叶 { if(du[i]==1) { q.push(i); treeleaf[i]=true; } } int u,s,v; while(!q.empty()) //删除叶子所在的边,直到只剩下一个环 { u=q.front(); q.pop(); s=g[u].size(); for(int i=0;i<s;++i) { v=g[u][i].t; du[v]--; if(du[v]==1) { treeleaf[v]=true; q.push(v); } } } for(int i=1;i<=n;++i) { if(!treeleaf[i]) { tidai[i]=i; dfs(i,-1,i); } } way1[x]=0; way2[x]=0; len1=len2=-1; dfs2(x,-1,x,y,0); //不通过所给边所需要走的路程 dfs3(x,-1,x,y,0); //通过所给边所需要走的路程 int ans1=0,ans2=0; printf("Case #%d:\n",tcase); for(int i=0;i<qt;++i) { scanf("%d%d",&a,&b); a=tidai[a]; b=tidai[b]; ans1=0;ans2=0; ans1=abs(way1[a]-way1[b]); ans2=abs(way2[a]-way2[b]); ans2=min(ans2,way2[n+1]-ans2); if(ans1>ans2) ans1=ans1-ans2; else ans1=0; printf("%d\n",ans1); } } return 0;}
- uestc 1717 Journey
- UESTC 1717 Journey
- UESTC 1717 Journey(改)
- UESTC Journey
- UESTC 1655 Journey
- UESTC 92 Journey(LCA)
- UESTC 576 —— Journey
- UESTC 92 Journey (LCA)
- UESTC 92 Journey(LCA)
- UESTC 92 Journey(LCA 裸题)
- UESTC - 92 Journey(LCA)1012四川省赛
- UESTC 92 Journey(LCA或树剖)
- Journey
- UESTC 1717 LCA+DIJ
- UESTC
- UESTC
- UESTC
- UESTC
- 小写转大写程序
- 侧边菜单栏 android-menudrawer
- 在2010版office word中,脚注或尾注的操作的相关方法
- C#的一些笔记(委托和反射)
- vim改变窗口的大小
- UESTC 1717 Journey
- mysql下的索引使用原则
- 我的cs第一个博客:windows下文件批量重命名简单方法
- hdu 1083 简单的二分匹配 Courses
- hadoop 的一些错误
- 为Linux MySQL数据库设置磁盘限额
- poj3349-hash
- 用python给MP3加封面图片,修改作者,专辑等信息
- 云计算的主要平台