HDU 5636 Shortest Path 分治+搜索剪枝
题意:bc round 74
分析(官方题解):
你可以选择分类讨论, 但是估计可能会写漏一些地方.
只要抽出新增边的端点作为关键点, 建立一个新图, 然后跑一遍floyd就好了. 复杂度大概O(6^2m)
注:然后我不会这种,这种floyd我觉得复杂度应该是复杂度应该是O(8^3m)
大概在千万级别,其实应该可以过,然后,其实只需要求单元最短路就行,然后是不是可以dij,然后就快一点
反正我也没写
我在比赛的时候写的是分治,考虑走不走新加的边每次走几条,以及走的顺序就好
然后全排列,时间复杂度是O(3^4m)的,大概在800w,然后由于这是单组样例800w*T
然后就超时了,然后比完赛,我就加了个剪枝,当前长度大于答案的时候,就返回
然后就1516ms过了,所以,以后记住要剪枝,不要图省事
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <vector> using namespace std; typedef long long LL; const int N=1e9+7; int o[3],x[3],y[3],n,m,s,t,ans,T; void dfs(int pos,int now,int sum) { if(sum>=ans)return; ans=min(ans,abs(t-now)+sum); int i=o[pos]; if(pos==3) { ans=min(ans,abs(t-now)+sum); return; } int tmp=sum+abs(now-x[i])+1; dfs(pos+1,y[i],tmp); tmp=sum+abs(now-y[i])+1; dfs(pos+1,x[i],tmp); dfs(pos+1,now,sum); } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0; i<3; ++i) { scanf("%d%d",&x[i],&y[i]); if(x[i]>y[i])swap(x[i],y[i]); } LL res=0; for(int i=1; i<=m; ++i) { scanf("%d%d",&s,&t); ans=0x3f3f3f3f; o[0]=0,o[1]=1,o[2]=2; dfs(0,s,0); o[0]=0,o[1]=2,o[2]=1; dfs(0,s,0); o[0]=1,o[1]=0,o[2]=2; dfs(0,s,0); o[0]=1,o[1]=2,o[2]=0; dfs(0,s,0); o[0]=2,o[1]=0,o[2]=1; dfs(0,s,0); o[0]=2,o[1]=1,o[2]=0; dfs(0,s,0); ans=min(ans,abs(s-t)); LL p=ans,q=i; res=(res+q*p%N)%N; } printf("%I64d\n",res); } return 0; }