• 牛客1080D tokitsukaze and Event (双向最短路)


    题目链接:https://ac.nowcoder.com/acm/contest/1080/D

    首先建两个图,一个是权值为a的图,一个是权值为b的图。

    从s起点以spfa算法跑权值为ai的最短路到t点,d1[ i ]数组就表示在权值为ai的图中,s点到i点的最短路。

    再从t点为起点spfa算法跑权值为bi的最短路到s点,d2[ i ]数组表示在权值为bi的图中,t点到s点的最短路。

    在节点i切换模式的最小伤害就是d1[ i ] + d2[ i ],倒着遍历取min即可。

    AC代码:

    #include<iostream>
    #include<cstdio> 
    #include<vector>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #define maxn 100005
    #define inf 0x3f3f3f3f
    using namespace std;
    struct node{
    	vector<int> w;
    	vector<int> num;
    }Ga[maxn],Gb[maxn];
    long long int inq[maxn],inq2[maxn],d1[maxn],d2[maxn],ans[maxn];
    void addedge(long long int u,long long int v,long long int a,long long int b){
    	Ga[u].num.push_back(v),Ga[u].w.push_back(a);
    	Ga[v].num.push_back(u),Ga[v].w.push_back(a);  
    	Gb[v].num.push_back(u),Gb[v].w.push_back(b); 
    	Gb[u].num.push_back(v),Gb[u].w.push_back(b);    	
    }
    void init(){
    	memset(d1,inf,sizeof(d1));
    	memset(d2,inf,sizeof(d2));
    	memset(inq,0,sizeof(inq));
    	memset(inq2,0,sizeof(inq2));
    	memset(ans,inf,sizeof(ans));
    }//初始化 
    int main(){
    	int n,m,s,t;
    	scanf("%d%d",&n,&m);
    	for(int i = 0;i<m;i++){
    	    long long int u,v,a,b;
    		scanf("%lld%lld%lld%lld",&u,&v,&a,&b);
    		addedge(u,v,a,b);  //建两个图                		
    	}
    	init();
    	scanf("%d%d",&s,&t);
    	queue<int> q;
    	q.push(s);
    	inq[s] = 1,d1[s] = 0;
    	while(!q.empty()){
    		int now = q.front();
    		q.pop();
    		inq[now] = 0;
    		for(int i = 0;i<Ga[now].num.size();i++ ){
    			int vex = Ga[now].num[i];
    			if(d1[vex] > d1[now] + Ga[now].w[i] ){
    				d1[vex] = d1[now] + Ga[now].w[i];
    				if(inq[vex] == 1){
    					continue;
    				} 
    				inq[vex] = 1;
    				q.push(vex);
    			} 
    		}
    	}//第一遍spfa 
    	queue<int> q2;
    	q2.push(t);
    	inq2[t] = 1,d2[t] = 0;
    	while(!q2.empty()){
    		int now = q2.front();
    		q2.pop();
    		inq2[now] = 0;
    		for(int i = 0;i<Gb[now].num.size();i++ ){
    			int vex = Gb[now].num[i];
    			if(d2[vex] > d2[now] + Gb[now].w[i]){
    				d2[vex] = d2[now] + Gb[now].w[i];
    				if(inq2[vex] == 1){
    					continue;
    				} 
    				inq2[vex] = 1;
    				q2.push(vex);
    			}
    		}
    	}//第二遍spfa 
    	for(int i = n;i>=0;i--){
    		ans[i] = min(ans[i+1],d1[i] + d2[i]);
    	}//倒着扫描 ans[i]就是在i点切换模式的最小伤害 
    	for(int i = 1;i<=n;i++){
    		if(i == n){
    			printf("%lld",ans[i]);
    			return 0;
    		}
    		printf("%lld
    ",ans[i]);
    	}
    }
  • 相关阅读:
    回顾C#3.0新特性(3)
    第五周作业
    第六周基础作业
    第三周syh
    基础作业
    第七周作业
    2019年春季学期第四周作业
    第八周作业
    .Net 反射
    C#中SqlParameter
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12129633.html
Copyright © 2020-2023  润新知