HDU 6005 Pandaland 最小环(最小生成树+LCA)
来源:互联网 发布:linux解压tar.xz文件 编辑:程序博客网 时间:2024/06/05 14:19
Pandaland
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 745 Accepted Submission(s): 166
Total Submission(s): 745 Accepted Submission(s): 166
Problem Description
Mr. Panda lives in Pandaland. There are many cities in Pandaland. Each city can be treated as a point on a 2D plane. Different cities are located in different locations.
There are also M bidirectional roads connecting those cities. There is no intersection between two distinct roads except their endpoints. Besides, each road has a cost w.
One day, Mr. Panda wants to find a simple cycle with minmal cost in the Pandaland. To clarify, a simple cycle is a path which starts and ends on the same city and visits each road at most once.
The cost of a cycle is the sum of the costs of all the roads it contains.
There are also M bidirectional roads connecting those cities. There is no intersection between two distinct roads except their endpoints. Besides, each road has a cost w.
One day, Mr. Panda wants to find a simple cycle with minmal cost in the Pandaland. To clarify, a simple cycle is a path which starts and ends on the same city and visits each road at most once.
The cost of a cycle is the sum of the costs of all the roads it contains.
Input
The first line of the input gives the number of test cases, T. T test cases follow.
Each test case begins with an integer M.
Following M lines discribes roads in Pandaland.
Each line has 5 integersx1,y1,x2,y2, w, representing there is a road with cost w connecting the cities on (x1,y1) and (x2,y2)
Each test case begins with an integer M.
Following M lines discribes roads in Pandaland.
Each line has 5 integers
Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the cost Mr. Panda wants to know.
If there is no cycles in the map, y is 0.
limits
If there is no cycles in the map, y is 0.
limits
∙1≤T≤50.
∙1≤m≤4000.
∙−10000≤xi,yi≤10000.
∙1≤w≤105.
Sample Input
250 0 0 1 20 0 1 0 20 1 1 1 21 0 1 1 21 0 0 1 591 1 3 1 11 1 1 3 23 1 3 3 21 3 3 3 11 1 2 2 22 2 3 3 33 1 2 2 12 2 1 3 24 1 5 1 4
Sample Output
Case #1: 8Case #2: 4
Source
2016 CCPC-Final
大致题意就是,给你一个图,然后让你在里面找一个最小的环。
说到找最小环,我很惊叹网上居然没有一个很好的算法。见到的算法都是用floyd的O(N^3)或者dijkstra的O(N^2logN)。但是这些显然都不能满足这题的要求。然后其实本题还加了一个条件,就是一定是一个平面图。一开始还拼命地去想平面图的性质,现在发现其实这些都无所谓。
这题,只要你联想到之前多校赛的第k小生成树的和,你就会知道如何下手。那题利用树边和非树边进行修改生成树和成环。这题也可以类似。由于要求是最小环,我们可以首先对这个图求最小生成树。根据树的性质,如果我们再添加上任意一条边,就会形成一个环。至于这个环的大小,我们可以用LCA来处理,计算出树上两点距离再加上边权结果就是这个环的大小。考虑最小环,我们只需要枚举这个边,然后找到最小的环即可。时间复杂度为O(V+E+NlogN),NlogN为排序。
事后看了下网上的题解,惊叹于居然大家都是dijkstra暴力做的,每次枚举一条边,然后把这条边删掉,边的两端设置为起点和终点,跑dijkstra。在跑的时候,每次dij到出现一个权值比当前ans要大的时候就停止dij。这样也是可以水过的,虽然理论是肯定会T的。具体见代码吧,感觉方法还是非常巧妙的,代码是队友写的,跟我风格不太符合:
#include<bits/stdc++.h>#define N 8010#define INF 100000000000#define LL long longusing namespace std;typedef pair<int,int> P;LL i,j,k,l,n,t,h;map<P,LL>s;vector <int> a[N],b[N];bool f[N];LL L[N],fa[N],anc[N][20],d[N],m;struct edge{ int a,b,c; bool operator < (const edge x)const { return c<x.c; }}E[N];void lable(LL x,LL ffa,LL p)//LCA标号{ for (LL i=0;i<a[x].size();i++)if (a[x][i]!=ffa) { d[a[x][i]]=d[x]+b[x][i]; fa[a[x][i]]=x; L[a[x][i]]=p+1; lable(a[x][i],x,p+1); }}void preprocess()//倍增预处理{ for (LL i=1;i<=n;i++) { anc[i][0]=fa[i]; for (LL j=1;(1<<j)<=n;j++) anc[i][j]=-1; } for (LL j=1;(1<<j)<=n;j++) for (LL i=1;i<=n;i++) if (anc[i][j-1]!=-1) { LL x=anc[i][j-1]; anc[i][j]=anc[x][j-1]; }}LL query(LL p,LL q)//求两点LCA{ LL log,i; if (L[p]<L[q]) swap(p,q); for (log=1;(1<<log)<=L[p];log++);log--; for (LL i=log;i>=0;i--) if (L[p]-(1<<i)>=L[q]) { p=anc[p][i]; } if (p==q)return p; //LCA?ap for (LL i=log;i>=0;i--) if (anc[p][i]!=-1 && anc[p][i]!=anc[q][i]) { p=anc[p][i]; q=anc[q][i]; } return fa[p];//LCA?afa[p]}int faa[N];int getfa(int x)//并查集……{ if (faa[x]==0)return x;else { int t=getfa(faa[x]); faa[x]=t; return t; }}bool used[N];int main(){ LL T,tt=0; scanf("%I64d",&T); while (T--) { t=0;s.clear(); memset(f,0,sizeof f);memset(d,0,sizeof d);memset(used,0,sizeof used); memset(a,0,sizeof a);memset(b,0,sizeof b); memset(faa,0,sizeof faa);memset(fa,0,sizeof fa); memset(L,0,sizeof L);memset(anc,0,sizeof anc); m=100000000000; scanf("%I64d",&n); for (i=1;i<=n;i++) { LL x,y; scanf("%I64d%I64d",&x,&y); if (!s[P(x,y)]) {j=++t;s[P(x,y)]=t;}else j=s[P(x,y)]; scanf("%I64d%I64d",&x,&y); if (!s[P(x,y)]) {k=++t;s[P(x,y)]=t;}else k=s[P(x,y)]; scanf("%I64d",&l); E[i]=edge{j,k,l}; } sort(E+1,E+n+1); for (i=1;i<=n;i++)//确定最小生成树,标记树边 { int p=getfa(E[i].a),q=getfa(E[i].b); if (p!=q) { used[i]=1; int v=E[i].a,u=E[i].b; a[v].push_back(u);b[v].push_back(E[i].c);//建树 a[u].push_back(v);b[u].push_back(E[i].c); faa[p]=q; } } int nn=n; n=t; for (i=1;i<=n;i++) { if (fa[i]==0) { fa[i]=i; lable(i,-1,0); } } preprocess(); for (i=1;i<=nn;i++)if (!used[i])//枚举非树边求最小环 { int v=E[i].a,u=E[i].b; LL w=d[v]+d[u]-d[query(v,u)]*2; if (w+E[i].c<m)m=w+E[i].c; } if (m==100000000000) m=0; printf("Case #%I64d: %I64d\n",++tt,m); } return 0;}
阅读全文
0 0
- HDU 6005 Pandaland 最小环(最小生成树+LCA)
- HDU 6005 Pandaland[最小生成树][LCA]
- 【最小环 && 离散化】HDU 6005 Pandaland
- HDU 6005 Pandaland(无向图最小环)
- Hdu 6005 Pandaland 无向图最小环:最短路剪枝
- HDU 6005 Pandaland(dijkstra + 剪枝)
- HDU 6005 Pandaland
- 过路费(最小生成树+lca)
- hdu 6005 Pandaland(dij+暴力)
- hdu 1599 (最小环问题)
- hdu 1599 最小环
- hdu 1599 最小环
- 最小生成树+LCA+uva11354
- <最小生成树><lca>Heatwave
- Pandaland HDU
- Pandaland HDU
- HPU图论专项(graph)【拓扑--二分图--最小生成树---树的直径---并查集--奇偶树---最小环---强联通】
- HDU 6005 Pandaland——dijkstra + 剪枝
- 实现线程同步的几种方式
- 积分域边界曲线为参数方程的二重积分的计算
- 回归1—pre_train_国庆不回家1
- 步入Hadoop
- Eclipse启动时报错Java was started but returned exit code=13
- HDU 6005 Pandaland 最小环(最小生成树+LCA)
- iOS 委托代理(delegate)入门
- 多线程面试知识点
- POJ3083:Children of the Candy Corn(DFS、BFS)
- 【java基础】17.10.7:static什么时候使用?有关静态变量(类变量)和静态方法(类方法)的解析
- 1.实现一个函数,可以左旋字符串中的k个字符。 AABCD左旋一个字符得到ABCDA AABCD左旋两个字符得到BCDAA 2.判断一个字符串是否为另外一个字符串旋转之后的字符串。 例如:给定s1
- 数字图像处理(一)
- Log4j 2架构
- Opencv3.2.0 SVM简单尝试