首页 > 其他 > 详细

洛谷多校第一周续

时间:2020-03-29 09:36:05      阅读:65      评论:0      收藏:0      [点我收藏+]

T122393 À la Volonté du Peuple

这题可以两种写法:

 点有两个最短路前驱会爆,
边不在最短路上会爆。
 
第一种方法:暴力枚举每一个边和点,复杂度是O(n+m),而不是O(n*n)的,因为n和m同阶,达不到n^n的复杂度。
如果这样会爆,跑最短路就直接爆了,spfa肯定是O(n^n)的。总复杂度O(n+m)
 
技术分享图片
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int inf=0x3f3f3f3f;
const int maxn=3e5+5;
struct edge{int v,w;edge(int a,int b){v=a,w=b;}};//v终点,w边权
struct node{
    int id,dis;//id点编号 dis暂时距离
    node(int a,int b){id=a,dis=b;}
    friend bool operator<(node a,node b){
    return a.dis>b.dis;//每次让距离小出队
    }
};
vector<edge>e[maxn];
int dis[maxn];//记录最短路
bool done[maxn];//记录是否找到最短路
    int n,m;
void dijkstra(){
    int s=1;//s起点 根据情况改
    for(int i=0;i<=n;i++)dis[i]=inf,done[i]=0;
    dis[s]=0;
    priority_queue<node>Q;
    Q.push(node(s,0));
    while(!Q.empty()){
    node u=Q.top();Q.pop();
    if(done[u.id])continue;
    done[u.id]=1;
    for(int i=0;i<e[u.id].size();i++){//遍历邻居
    edge y=e[u.id][i];
    if(done[y.v])continue;
    if(dis[y.v]>y.w+dis[u.id]){
    dis[y.v]=y.w+u.dis;
    Q.push(node(y.v,dis[y.v]));//更新最短路
    }
    }
    }
}
int main(){
    cin>>n>>m;
    while(m--){
    int a,b,c;
    scanf("%d %d %d",&a,&b,&c);
    e[a].pb(edge(b,c));
    if(a!=b)e[b].pb(edge(a,c));
    }
    dijkstra();
    int ans=0,cnt;
    for(int i=1;i<=n;i++){
        cnt=0;
    for(int j=0;j<e[i].size();j++){
    int y=e[i][j].v;
    if(dis[i]==dis[y]+e[i][j].w)cnt++;
    if(i>=y&&dis[i]<dis[y]+e[i][j].w&&dis[y]<dis[i]+e[i][j].w)ans++;
    }
    if(cnt>1)ans++;
    }
    cout<<ans<<endl;
    return 0;
}
View Code

第二种方法:

比较鬼。

最短路前驱为1,不炸。
最短路前驱>=2,会少炸x-1次

洛谷多校第一周续

原文:https://www.cnblogs.com/littlerita/p/12590363.html

(1)
(1)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!