• 【xsy1162】鬼计之夜 最短路+二进制拆分


    套路题(然而我没看题解做不出来)

    题目大意:给你一个$n$个点,$m$条有向边的图。图中有$k$个标记点,求距离最近的标记点间距离。

    数据范围:$n,m,k≤10^5$。

    设$p_i表$示第$i$个标记点的编号,设$K$为最小正整数,满足$2^K≥k$。

    我们在原图中新建点$S$和点$T$,做$2K$次最短路。

    对于$K$个二进制位,将$k$个关键点分成两部分,以其中一部分为起点,向另一部分做最短路即可。

    时间复杂度:$O(m log n log k)$

     1 #include<bits/stdc++.h>
     2 #define M 200005
     3 #define L long long
     4 #define INF (1LL<<60)
     5 using namespace std;
     6 
     7 struct edge{L u,v,next;}e[M*2]={0}; L head[M]={0},use=0;
     8 void add(L x,L y,L z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
     9 L vis[M]={0},S,T,n,m,k;
    10 
    11 struct node{
    12     L u,dis; node(){u=dis=0;}
    13     node(L U,L Dis){u=U; dis=Dis;}
    14     friend bool operator <(node a,node b){return a.dis>b.dis;}
    15 };priority_queue<node> q;
    16 
    17 L bfs(){
    18     memset(vis,0,sizeof(vis));
    19     q.push(node(S,0));
    20     while(!q.empty()){
    21         node U=q.top(); q.pop();
    22         if(U.u==T) return U.dis;
    23         if(vis[U.u]) continue;
    24         vis[U.u]=1; 
    25         for(L i=head[U.u];i;i=e[i].next)
    26         if(vis[e[i].u]==0) 
    27         q.push(node(e[i].u,U.dis+e[i].v));
    28     }
    29     return INF;
    30 }
    31 L u[M]={0},v[M]={0},w[M]={0},id[M]={0};
    32 main(){
    33     scanf("%lld%lld%lld",&n,&m,&k); S=0; T=n+1;
    34     for(L i=1;i<=m;i++) scanf("%lld%lld%lld",u+i,v+i,w+i);
    35     for(L i=1;i<=k;i++) scanf("%lld",id+i);
    36     L ans=INF;
    37     for(L p=1;p<=k;p<<=1){
    38         memset(head,0,sizeof(head)); use=0;
    39         for(L i=1;i<=m;i++) add(u[i],v[i],w[i]);
    40         for(L i=1;i<=k;i++)
    41         if(p&i) add(S,id[i],0);
    42         else add(id[i],T,0);
    43         ans=min(ans,bfs());
    44         
    45         memset(head,0,sizeof(head)); use=0;
    46         for(L i=1;i<=m;i++) add(u[i],v[i],w[i]);
    47         for(L i=1;i<=k;i++)
    48         if(p&i) add(id[i],T,0);
    49         else add(S,id[i],0);
    50         ans=min(ans,bfs());
    51     }
    52     cout<<ans<<endl;
    53 }
  • 相关阅读:
    java 9+版本中,接口的内容总结
    发红包的案例
    java中成员变量和局部变量的区别
    分别使用面向对象和面向过程两个不同的思路编写代码,打印输出一个数组,输出数组的格式:“[10,20,30,40,50]”
    题目要求:不能使用新数组,就用原来的唯一的数组进行反转
    request.getRequestDispatcher()和response.sendRedirect()区别
    Maven是什么
    字符串中的各种方法
    数组中的各种方法
    字符串的模式匹配方法-match-search-repalce
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10354531.html
Copyright © 2020-2023  润新知