当前位置: 首页 > news >正文

深圳网站建设网站凡科建站的优势

深圳网站建设网站,凡科建站的优势,蚌埠网站排名,深圳网站建设便宜信科网络今天讲最短路统计和分层图 目录 题目:LCA 思路: 题目:最短路计数 思路: 题目:社交网络 思路: 题目:飞行路线 思路: 题目:第二短路 思路: 题目&a…

今天讲最短路统计和分层图

目录

题目:LCA 

思路:

题目:最短路计数

思路:

题目:社交网络

思路:

题目:飞行路线 

思路:

题目:第二短路

思路:


        

        

题目:LCA 

        

思路:

        

非常明显了,之前就说过倍增迭代就是一个一个选区间使总长度达到 M(凑一个数),用不大于它最大的二的次幂,减去之后,再重复这个过程。所以LCA+倍增逼近是最快的。

                

#include<bits/stdc++.h> //最近公共祖先LCA P3379:给一棵数,求任意两点的LCA 
using namespace std;
const int maxn=500002;
int n,m,s,tot=0;
int head[maxn],d[maxn],p[maxn][21];//d存的是深度(deep),p[i][j]存的从i向上走2的j次方那么长的路径到的父节点
struct node{int v,next;}e[maxn*2];//存数要开两倍
void add(int u,int v){e[++tot]={v,head[u]};head[u]=tot;}     void dfs(int u,int fa)// 首先进行的预处理,将所有点的deep和p的初始值dfs出来
{d[u]=d[fa]+1; p[u][0]=fa;  //处理深度,父节点for(int i=1;(1<<i)<=d[u];i++)//i<log(d[u]) 处理每个u的st表p[u][i]=p[p[u][i-1]][i-1];for(int i=head[u];i;i=e[i].next){ //处理u的孩子的st表int v=e[i].v;if(v!=fa) dfs(v,u);//只能向下走,不能向上走}
}                              
int lca(int a,int b) //非常标准的lca查找(两次逼近)
{if(d[a]>d[b]) swap(a,b);   //保证a是在b结点上方(d[b]大)for(int i=20;i>=0;i--){if(d[a]<=d[b]-(1<<i)) b=p[b][i];//向上逼近(b向上移到和a同一个深度)}  if(a==b) return a;  //特判for(int i=20;i>=0;i--){if(p[a][i]==p[b][i]) continue; //向上逼近(A和B一起向上,不断逼近最下端的公共祖先)else a=p[a][i],b=p[b][i];     }return p[a][0];  //找出最后a值的数字
}
int main()
{int a,b;scanf("%d%d%d",&n,&m,&s);//n个结点,m次询问,s是树根编号for(int i=1;i<n;i++){scanf("%d%d",&a,&b);add(a,b); add(b,a); //无向图,要加两次              }dfs(s,0);for(int i=1;i<=m;i++){scanf("%d%d",&a,&b);printf("%d\n",lca(a,b));}return 0;
}

        

         

题目:最短路计数

                  

思路:

        

注意到每条路径的权值都是1,难怪结果会那么大。

        

dikjkstra和spfa版本最短路计数:
1,维护最短路时产生的:那就是映射关系(因为引入的是周围点,相当于ans[v]=ans[cur]*1)
2,新最短路:发现了新的最短路就相加

        
floyd版本最短路计数:
1,维护最短路时产生的:(因为引入的是任意点,故ans[i][j]=ans[i][k]*ans[k][j])
2,新最短路:发现了新的最短路就相加

、        

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=1e6+5,M=2e6+5;
int mod=100003,n,m,tot=0;
int head[N],vis[N],dis[N],ans[N];
priority_queue<pii,vector<pii>,greater<pii>>Q;
struct node {int to;int next;}e[M*2];
void add(int u,int v){e[++tot]=(node){v,head[u]};head[u]=tot;}
void dijkstra(int s){memset(dis,0x3f,sizeof(dis));Q.push({0,s});dis[s]=0;ans[s]=1;while(!Q.empty()){int cur=Q.top().second;Q.pop();if(vis[cur])continue;//跳不跳无所谓,无非耗点时间vis[cur]=1;for(int i=head[cur];i;i=e[i].next){int v=e[i].to;if(dis[cur]+1<dis[v])dis[v]=dis[cur]+1,ans[v]=ans[cur],Q.push({dis[v],v});//映射最短路(路过此点可以变短,那么最短路就和它有关)else if(dis[cur]+1==dis[v])ans[v]+=ans[cur],ans[v]%=mod;//新最短路(发现了另外的最短路就相加)}}
}
int main(){cin>>n>>m;int x,y;for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);add(x,y);add(y,x);}dijkstra(1);//spfa(1);for(int i=1;i<=n;i++){cout<<ans[i]<<'\n';}
}

                 

//spfa版本:这个版本更快!!!!
void spfa(int s){memset(dis,0x3f,sizeof(dis));queue<int>q;vis[s]=1;q.push(s);dis[s]=0;ans[s]=1;while(!q.empty()){int cur=q.front();q.pop();vis[cur]=0;for(int i=head[cur];i;i=e[i].next){int v=e[i].to;if(dis[cur]+1<dis[v]){dis[v]=dis[cur]+1;ans[v]=ans[cur];if(!vis[v])q.push(v),vis[v]=1;	}else if(dis[cur]+1==dis[v])ans[v]+=ans[cur],ans[v]%=mod;}}
}

        

        

题目:社交网络

                

思路:

        

点i的重要程度=∑从s到t的且经过i最短路条数/从s到t的最短路条数(s!=i,t!=i)

主要还是floyd算法,求出每个(i,j)对每个k的重要程度为ans[k]
求到某点时最短路径数:
1,只要最短路更新,那么最短路个数也要更新
2,如果发现了新的最短路,那么就相加
        

#include <bits/stdc++.h>
using namespace std;   
typedef long long ll;
const int N=110;
ll INF,dis[N][N],e[N][N];//e[i][j]表示(i,j)的最短路径数
double ans[N];//每个点的重要程度
int main(){int n,m;ll x,y,z;cin>>n>>m;memset(dis,0x7f,sizeof(dis));INF=dis[1][1];//初始化INF无穷大for(int i=1;i<=m;i++){scanf("%lld%lld%lld",&x,&y,&z);dis[x][y]=dis[y][x]=z;e[x][y]=e[y][x]=1;//初始化e[i][j]}for(int i=1;i<=n;i++)  dis[i][i]=0;//对角线为0,但是不写也对其余任何边都没有影响,写不写随你for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(dis[i][k]==INF||dis[k][j]==INF)continue;//有不通的就直接跳过if(dis[i][j]>dis[i][k]+dis[k][j]){dis[i][j]=dis[i][k]+dis[k][j];//每个边只会更新一次,即当前最优e[i][j]=e[i][k]*e[k][j];//只要最短路更新,则最短路对应的个数也要更新即可continue;}if(dis[i][j]==dis[i][k]+dis[k][j]){//找到了第二条最短路,就相加e[i][j]+=e[i][k]*e[k][j];}}for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(i==j||j==k||i==k)continue;if(dis[i][j]==dis[i][k]+dis[k][j])//对k遍历每个(i,j)ans[k]+=(1.0*e[i][k]*e[k][j])/e[i][j];}for(int i=1;i<=n;i++)printf("%0.3f\n",ans[i]);
}

       

         

题目:飞行路线 

        

                 

思路:

        

 一个图中任意两个点都可以权值变成0,最多有k次,我们常常建立k层的分层图,相邻层所有点建立权值为0的立体边,然后跑最短路即可
        

#include <bits/stdc++.h> 
using namespace std;
int cnt,head[110005];
int dis[110005];
bool vis[110005]; //标记当前白点,如果不想用vis,也可以判断取出元素的dis和dis数组中值是否一样
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>> > Q; //堆优化(first是值,second是下标)
struct Edge{ int to,w,next;}e[2500001];
void add(int u,int v,int w) { e[++cnt]=(Edge){v,w,head[u]}; head[u]=cnt;}
void Dijkstra(int s)//dijktra+堆优化
{memset(dis,0x3f,sizeof(dis));dis[s]=0;Q.push(make_pair(0,s));while(!Q.empty())  //必须用empty, size是求大小的,会慢一些 !!!{int u=Q.top().second; Q.pop();if(vis[u]) continue; //已经是白点的就跳过vis[u]=1; //标记成白点for(int i=head[u];i;i=e[i].next){int v=e[i].to,w=e[i].w;if(dis[v]>dis[u]+w) dis[v]=dis[u]+w,Q.push(make_pair(dis[v],v));}}    
}int main()
{int n,m,k,s,t;cin>>n>>m>>k>>s>>t; //城市数,航线数,免费次数,起始城市号,终点城市号int u,v,c;for(int i=0;i<m;++i){cin>>u>>v>>c;//两个城市航线,费用for(int j=0;j<=k;++j){//建立每层图add(u+j*n,v+j*n,c);add(v+j*n,u+j*n,c);if(j!=k){//第k层下面没有了,就别建了add(u+j*n,v+(j+1)*n,0); //分层图:所有相邻层间:上下层u,v的权值为0add(v+j*n,u+(j+1)*n,0);}}}for(int i=1;i<=k;++i){add(t+(i-1)*n,t+i*n,0);}//处理奇葩数据Dijkstra(s);printf("%d",dis[t+k*n]);return 0;
}

         

         

题目:第二短路

                 

思路:

#include<bits/stdc++.h>
using namespace std;   
typedef pair<int,int> pii;
const int N=5005,M=100005;
int n,m,tot,flag;
int head[N],d1[N],d2[N],vis[N];
priority_queue<pii,vector<pii>,greater<pii> > Q;
struct node{int to;int w;int next;}e[M*2];
void add(int u,int v,int w){e[++tot]=(node){v,w,head[u]};head[u]=tot;}
void dijkstra(int s){memset(d1,0x3f,sizeof(d1));//d1存放第一短路memset(d2,0x3f,sizeof(d2));//d2存放第二短路Q.push(make_pair(0,s));d1[s]=0;while(!Q.empty()){int cur=Q.top().second;Q.pop();if(vis[cur])continue;//vis数组可有可无,即便旧白点引入也掀不起变化,无非多走了几步vis[cur]=1;for(int i=head[cur];i;i=e[i].next){int v=e[i].to,w=e[i].w;flag=0;if(d1[cur]+w<d1[v])d2[v]=d1[v],d1[v]=d1[cur]+w,flag=1;//维护最短路,更新前的最短路就是次短路if(d1[cur]+w>d1[v]&&d1[cur]+w<d2[v])d2[v]=d1[cur]+w,flag=1;//最短路没有变化,更新次短路if(d2[cur]+w<d2[v])d2[v]=d2[cur]+w,flag=1;//维护次短路,如果d2[s]初始化成0,那么这个地方就出问题了if(flag)Q.push(make_pair(d1[v],v));}}
}
int main(){cin>>n>>m;int u,v,w;for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);}dijkstra(1);cout<<d2[n];
}

http://www.khdw.cn/news/43214.html

相关文章:

  • 建网站郑州免费b2b推广网站
  • 小学生家长网站建设需求seddog站长之家
  • 专业专业的网站开发代写新闻稿
  • 网站开发项目报价疫情防控数据
  • 做平台的网站有哪些功能吗百度seo算法
  • 商城网站系统快推达seo
  • 电脑上如何做网站自建站平台
  • 机票网站建设公司好青岛优化网站关键词
  • 高端网站制作建设培训机构排名一览表
  • 郑州市进一步调整优化防控措施sem和seo哪个工作好
  • 网站UI怎么做福建百度代理公司
  • skype在网站上怎么做链接百度怎么优化关键词排名
  • 百度站长工具网站认证seo权重优化软件
  • 怎样做的网站内网外网都能用百度官网下载安装到桌面上
  • 网站优化知识资讯电商运营方案
  • 安全培训网站批量关键词排名查询工具
  • 有多人做网站是个人备案网络推广的优势
  • 如何做网站国际化网络推广公司哪里好
  • 无锡网站建设选众鼎上海百度竞价点击软件
  • iis2008如何做网站赣州seo外包
  • html网页制作实验报告网站关键字排名优化
  • 白云区建材网站建设推广标题优化seo
  • 做网站线进行seo网站建设
  • 郑州网站制作价格太原seo优化
  • 电影网站建设java肇庆百度快照优化
  • 营改增后网站建设发票税率多少钱西安seo经理
  • eclipse网站开发教程今日军事新闻
  • 做外贸网站客服做seo推广公司
  • 建网站做相亲菏泽seo
  • 在网站里继费百度商店