1 条题解

  • 0
    @ 2022-3-2 14:22:58

    考虑那个式子实际上就是删掉最大值加上最小值。

    把他看成将一条边乘二,一条边删掉,然后发现这个东西恰好满足最短路。

    然后直接记录是否乘二,是否删掉,跑分层图最短路就好了。


    代码
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll,int> Int;
    const int N=2e5+5;
    int n,m,id[N][4],vis[N*4];
    ll dis[N*4];
    vector<Int> e[N*4];
    priority_queue<Int,vector<Int>,greater<Int> > q;
    void add(int x,int y,int z){
    	e[id[x][0]].emplace_back(id[y][0],z);
    	e[id[y][1]].emplace_back(id[x][1],z);
    	e[id[y][2]].emplace_back(id[x][2],z);
    	e[id[y][3]].emplace_back(id[x][3],z);
    	e[id[x][0]].emplace_back(id[y][1],0);
    	e[id[x][0]].emplace_back(id[y][2],2*z);
    	e[id[x][0]].emplace_back(id[y][3],z);
    	e[id[x][1]].emplace_back(id[y][3],2*z);
    	e[id[x][2]].emplace_back(id[y][3],0);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)id[i][0]=i,id[i][1]=n+i,id[i][2]=2*n+i,id[i][3]=3*n+i;
    	for(int i=1;i<=m;i++){
    		int x,y;ll z;
    		scanf("%d%d%lld",&x,&y,&z);
    		add(x,y,z),add(y,x,z);
    	}
    	memset(dis,63,sizeof(dis));
    	memset(vis,0,sizeof(vis));
    	dis[1]=0;
    	priority_queue<Int,vector<Int>,greater<Int> > q;
    	q.push(make_pair(0,1));
    	while(!q.empty()){
    		int x=q.top().second;q.pop();
    		if(vis[x])continue;
    		vis[x]=1;
    		for(auto i:e[x]){
    			int y=i.first,z=i.second;
    			if(dis[y]>dis[x]+z){
    				dis[y]=dis[x]+z;
    				q.push(make_pair(dis[y],y));
    			}
    		}
    	}
    	for(int i=2;i<=n;i++)printf("%lld ",dis[id[i][3]]);
    }
    
    • 1

    信息

    ID
    84
    时间
    3000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者