题意:给你N个点M条边,M-N<=20,有1e5个询问,询问两点的最短距离。保证没有自环和重边。

题解:连题目都在提示你这个20很有用,所以如果是颗树的话那任意两点的最短距离就是求一下lca搞一搞的问题。所以可以先求出最小生成树,那么会剩下最多42个点,我们知道非树边可能更优,所以对于每条非树边对应的两个点跑一遍dij,尝试更新答案ans=min(ans,dis[i][u]+dis[i][v])。正确性:可能通过多条非树边?在跑dij时其实已经处理出了最短的路,如果是通过多条非树边更优,那么它记录的就是这样的值。为什么这个题别人的代码那么短。。。

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define ls x<<1
#define rs x<<1|1
#define ull unsigned long long
#define _mp make_pair
#define ldb long double
using namespace std;
const int maxn=1e5+100;
const ll inf=1e18;
int bcg[maxn];
struct Edge
{
int u,v,nxt;
ll w;
}edge[maxn*2],edge1[maxn*2];
vector<Edge>vec[maxn];
struct Node{
ll p;
int v;
friend bool operator<(Node a,Node b)
{
return a.p>b.p;
}
Node(){}
Node(ll x,int y){p=x,v=y;}
};
int head[maxn],head1[maxn];
ll deep[maxn];
int depth[maxn];
int bian[maxn*2];
ll dis[50][maxn];
int lca[maxn][25];
int vis[maxn];
int cnt,cnt1,tot;
int n,m;
int findd(int x)
{
return bcg[x]==x?bcg[x]:bcg[x]=findd(bcg[x]);
}
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
void add_e1(int x,int y,ll w)
{
++cnt1;edge1[cnt1].u=x;edge1[cnt1].v=y;edge1[cnt1].w=w;edge1[cnt1].nxt=head1[x];head1[x]=cnt1;
}
void add_e(int x,int y,ll w)
{
++cnt;edge[cnt].u=x;edge[cnt].v=y;edge[cnt].w=w;edge[cnt].nxt=head[x];head[x]=cnt;
}
int merges(int x,int y)
{
int xx=findd(x);
int yy=findd(y);
if(xx!=yy)
{
bcg[xx]=yy;
return 1;
}
return 0;
}
void init()
{
cnt=cnt1=0;
tot=0;
memset(deep,0,sizeof(deep));
memset(head,0,sizeof(head));
memset(head1,0,sizeof(head1));
}
void dfs(int x,int ff)
{
lca[x][0]=ff;
for(int i=1;i<=20;i++)lca[x][i]=lca[lca[x][i-1]][i-1];
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].v;
if(v==ff)continue;
deep[v]=deep[x]+edge[i].w;
depth[v]=depth[x]+1;
dfs(v,x);
}
}
int LCA(int x,int y)
{
if(depth[x]<depth[y])swap(x,y);
int ff=depth[x]-depth[y];
for(int i=20;i>=0;i--)
{
if(ff&(1<<i))x=lca[x][i];
}
if(x==y)return y;
for(int i=20;i>=0;i--)
{
if(lca[x][i]!=lca[y][i])x=lca[x][i],y=lca[y][i];
}
return lca[y][0];
}
priority_queue<Node>que;
void dij(int id,int x)
{
for(int i=0;i<=n+4;i++)
{
dis[id][i]=inf;
vis[i]=0;
}
dis[id][x]=0;
while(!que.empty())que.pop();
que.push(Node(0,x));
while(!que.empty())
{
Node vv=que.top();que.pop();
if(vis[vv.v]||vv.p>dis[id][vv.v])continue;
vis[vv.v]=1;
for(int i=0;i<(int)vec[vv.v].size();i++)
{
Edge k=vec[vv.v][i];
int sw=k.v;
if(vis[sw])continue;
if(dis[id][sw]>dis[id][vv.v]+k.w)
{
dis[id][sw]=dis[id][vv.v]+k.w;
que.push(Node(dis[id][sw],sw));
}
} }
}
int main()
{
scanf("%d%d",&n,&m);
int u,v;
ll w;
init();
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&u,&v,&w);
add_e1(u,v,w);
vec[u].push_back((Edge){u,v,0,w});
vec[v].push_back((Edge){v,u,0,w});
}
sort(edge1+1,edge1+cnt1+1,cmp);
for(int i=1;i<=n+4;i++)bcg[i]=i;
for(int i=1;i<=cnt1;i++)
{
int x=edge1[i].u,y=edge1[i].v;
if(merges(x,y))
{
add_e(x,y,edge1[i].w);
add_e(y,x,edge1[i].w);
}
else
{
bian[++tot]=x;
bian[++tot]=y;
}
}
depth[1]=0;
deep[1]=0;
dfs(1,0);
sort(bian+1,bian+1+tot);
int sz=unique(bian+1,bian+1+tot)-(bian+1);
for(int i=1;i<=sz;i++)
{
dij(i,bian[i]);
}
int q;
scanf("%d",&q);
int x,y;
while(q--)
{
scanf("%d%d",&x,&y);
ll ans=inf;
int pq=LCA(x,y); ans=deep[x]+deep[y]-2*deep[pq];
for(int i=1;i<=sz;i++)
{
ans=min(ans,dis[i][x]+dis[i][y]);
}
cout<<ans<<"\n";
}
return 0;
}

  

Codeforces 1051E. Vasya and Big Integers的更多相关文章

  1. Codeforces 1051E Vasya and Big Integers&1051F The Shortest Statement

    1051E. Vasya and Big Integers 题意 给出三个大整数\(a,l,r\),定义\(a\)的一种合法的拆分为把\(a\)表示成若干个字符串首位相连,且每个字符串的大小在\(l, ...

  2. CodeForces - 837E - Vasya's Function | Educational Codeforces Round 26

    /* CodeForces - 837E - Vasya's Function [ 数论 ] | Educational Codeforces Round 26 题意: f(a, 0) = 0; f( ...

  3. CodeForces - 1051E :Vasya and Big Integers(Z算法 & DP )

    题意:给定字符串S,A,B.现在让你对S进行切割,使得每个切割出来的部分在[A,B]范围内,问方案数. 思路:有方程,dp[i]=Σ dp[j]   (S[j+1,i]在合法范围内).    假设M和 ...

  4. Codeforces 1107G Vasya and Maximum Profit 线段树最大子段和 + 单调栈

    Codeforces 1107G 线段树最大子段和 + 单调栈 G. Vasya and Maximum Profit Description: Vasya got really tired of t ...

  5. Codeforces 837E. Vasya's Function

    http://codeforces.com/problemset/problem/837/E   题意: f(a, 0) = 0; f(a, b) = 1 + f(a, b - gcd(a, b)) ...

  6. Codeforces 837E Vasya's Function - 数论

    Vasya is studying number theory. He has denoted a function f(a, b) such that: f(a, 0) = 0; f(a, b) = ...

  7. Codeforces 493C - Vasya and Basketball

    C. Vasya and Basketball 题目链接:http://codeforces.com/problemset/problem/493/C time limit per test 2 se ...

  8. codeforces 493B.Vasya and Wrestling 解题报告

    题目链接:http://codeforces.com/problemset/problem/493/B 题目意思:给出 n 个 techniques,每个 technique 的值为 ai. ai & ...

  9. codeforces 493A. Vasya and Football 解题报告

    题目链接:http://codeforces.com/contest/493/problem/A 题目意思:给出两个字符串,分别代表 home 和 away.然后有 t 个player,每个playe ...

随机推荐

  1. Jquery 选择器 特殊字符 转义字符

    1.Jquery   选择器 id包含特殊字符,加双斜线 \\ 例 <input type="text" id="dbo_HouseInfo.HouseResour ...

  2. Oracle 同义词(Synonym)

    同义词(Synonym)是表.索引.视图等模式对象的一个别名.通过模式对象创建同义词,可以隐藏对象的实际名称和所有者信息,隐藏分布式数据库中远程对象的设置信息,由此为对象提提供一定的安全性保证.同义词 ...

  3. C# Note22: 《Effective C#》笔记

    参考:<Effective C#>快速笔记(一)- C# 语言习惯 参考:<Effective C#>快速笔记(二)- .NET 资源托管 参考:<Effective C ...

  4. elasticsearch概念及倒排索引简单介绍

    一.概念 集群:一个或者多个节点组织在一起 节点:一个节点是集群中的一个服务器,由一个名字来标识,默认是一个随机的漫威角色名字. 分片:将索引划分为多份的能力,允许水平分割和扩展容量,多个分片相应请求 ...

  5. fiddler学习笔记2 字段说明;移动设备、解密证书

    # :           抓取顺序从1开始递增 result:    http 请求状态 protocol:   请求使用的协议如:http https ftp Host:         请求地址 ...

  6. PHP超级全局变量、魔术变量和魔术函数

    PHP超级全局变量(9个) $GLOBALS 储存全局作用域中的变量 $_SERVER 获取服务器相关信息 $_REQUEST 获取POST和GET请求的参数 $_POST 获取表单的POST请求参数 ...

  7. Lodop背景图无图片时显示放大叉号问题

    正常情况下,如果指定图片路径中,图片不存在或指定错误的路径,会因为找不到图片显示叉号,Lodop背景图如果设置了背景图宽度高度控制,显示的叉号也会被相应的放大,形成放大的模糊的图案,看起来就像是黑色边 ...

  8. jpa 比较复杂的查询和用in关键字

    in关键字使用代码

  9. Jira的搭建

    一.环境准备 jira7.2的运行是依赖java环境的,也就是说需要安装jdk并且要是1.8以上版本,如下: java -version 除此之外,我们还需要为jira创建对应的数据库.用户名和密码, ...

  10. controller层负责创建类传递类给service;service层负责逻辑编写调用dao层 将编写后的类传递到dao层,保证事务的正确性;dao层负责数据的持久化

    controller层负责创建类传递类给service:service层负责逻辑编写调用dao层 将编写后的类传递到dao层,保证事务的正确性:dao层负责数据的持久化