• 【题解】 [SDOI2009] Elaxia的路线(最短路+拓扑排序)


    懒得复制,戳我戳我

    Solution:

    • 题目大概意思就是找两条最短路后,找出最长公共部分
    • 我们就只用以四个点为源点开始走(SPFA),然后我们就只用遍历每条边然后建立一个新的拓扑图,然后随便搞一下就出来了
    • 另外在建新图时不要跑边入队,不然一次性入队的点太多就会爆炸,只用遍历每一条边,然后把公共边从距离小的点连向距离大的点就行了
    • 最后面就是一遍拓扑序dp一下

    Code:

    //It is coded by Ning_Mew on 4.6
    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=1507;
    const int maxm=1507*1507;
    
    int n,m,ans;
    int s[3],t[3];
    int head[maxn],cnt=0,hd[maxn],ct=0;
    struct Edge{
    	int from,dis,to,nxt;
    }edge[maxm],ee[maxm];
    int dist[5][maxn],vis[maxn],in[maxn],dp[maxn];
    bool instack[maxn];
    
    void add(int from,int to,int dis,int num){
    	if(num==1){
    		edge[++cnt].nxt=head[from];
    		edge[cnt].from=from;
    		edge[cnt].to=to;
    		edge[cnt].dis=dis;
    		head[from]=cnt;
    	}else{
    		ee[++ct].nxt=hd[from];
    		ee[ct].to=to;
    		ee[ct].dis=dis;
    		hd[from]=ct;
    	}return;	
    }
    void SPFA(int k,int ls,int num){
    	queue<int>Q; while(!Q.empty())Q.pop();
    	Q.push(k);vis[k]=ls;
    	dist[num][k]=0;
    	while(!Q.empty()){
    		int u=Q.front();Q.pop();vis[u]=ls-1;
    		for(int i=head[u];i!=0;i=edge[i].nxt){
    			int v=edge[i].to;
    			if(dist[num][v]>dist[num][u]+edge[i].dis){
    				dist[num][v]=dist[num][u]+edge[i].dis;
    				if(vis[v]!=ls){
    					Q.push(v);vis[v]=ls;
    				}
    			}
    		}	
    	}
    }
    void find(){
    	for(int i=1;i<=cnt;i+=2){
    		int u=edge[i].from,v=edge[i].to,dis=edge[i].dis;
    		bool in1=false,in2=false;
    		if(dist[1][u]+dis+dist[2][v]==dist[1][ t[1] ]||dist[2][u]+dis+dist[1][v]==dist[1][ t[1] ])in1=true;
    		if(dist[3][u]+dis+dist[4][v]==dist[3][ t[2] ]||dist[4][u]+dis+dist[3][v]==dist[3][ t[2] ])in2=true;
    		if(in1&&in2){
    			if(dist[1][u]<dist[1][v])add(u,v,dis,2),in[v]++,instack[u]=true,instack[v]=true;
    			else add(v,u,dis,2),in[u]++,instack[u]=true,instack[v]=true;
    		}
    	}return;
    }
    void topsort(){
    	memset(dp,-0x5f,sizeof(dp));
    	queue<int>Q;while(!Q.empty())Q.pop();
    	for(int i=1;i<=n;i++){
    		if(instack[i]&&in[i]==0)Q.push(i),dp[i]=0;
    	}
    	while(!Q.empty()){
    		int u=Q.front();Q.pop();
    		for(int i=hd[u];i!=0;i=ee[i].nxt){
    			int v=ee[i].to;
    			in[v]--;if(in[v]==0)Q.push(v);
    			dp[v]=max(dp[v],dp[u]+ee[i].dis);
    		}
    	}return;
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	scanf("%d%d%d%d",&s[1],&t[1],&s[2],&t[2]);
    	for(int i=1;i<=m;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);add(x,y,z,1);add(y,x,z,1);}
    	//cout<<"build finished!"<<endl;
    	memset(instack,false,sizeof(instack));
    	memset(dist,0x5f,sizeof(dist));
    	SPFA(s[1],2,1); SPFA(t[1],2,2); SPFA(s[2],3,3); SPFA(t[2],3,4);
    	//for(int i=1;i<=n;i++)cout<<i<<" dist:"<<dist[1][i]<<" dist2:"<<dist[2][i]<<endl;cout<<endl;
    	//for(int i=1;i<=n;i++)cout<<i<<" dist:"<<dist[3][i]<<" dist2:"<<dist[4][i]<<endl;
    	find(); 
    	topsort();
    	ans=-0x5f;
    	for(int i=1;i<=n;i++){ans=max(ans,dp[i]);}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    maven更改编译环境的java版本
    ConcurrentHashMap和HashMap的一点区别
    TCP/IP协议中网关和子网掩码概念
    同步和异步关注的是消息通信机制,阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态
    maven中央仓库访问速度太慢的解决办法
    BIOS设置和CMOS设置的区别与联系
    PL/SQL 如何查看当前连接信息以及SQL PLUS如何指定IP地址
    【转载】C#常用数据库Sqlserver中DATEPART() 函数
    【转载】 Sqlserver中DateAdd()函数
    【转载】C#递归删除文件夹目录及文件
  • 原文地址:https://www.cnblogs.com/Ning-Mew/p/8737127.html
Copyright © 2020-2023  润新知