zoukankan      html  css  js  c++  java
  • Layout G

    Layout G

    题目传送门qwq

    前言

    不得不说,这道题读下来完全就是 模板题!当然除最后三个万恶的(hack)数据以外

    如果有不了解的差分约束系统的,珂以看这篇博客


    分析

    • (N)个点,给出(M_L)(≤)的关系,(M_D)(≥)的关系

    这....不就是约束条件嘛!那最直观的解决方法不就是差分约束系统嘛!

    • 对于差分约束系统的题,我们还是要先判断是跑最短路还是最长路

    继续看题,发现要求出从(1)(N)最大距离

    我们知道,求最大解就是跑最短路,求最小解就是跑最长路(不知道的还是上面那篇博客qwq)

    初步思路已经出来了:跑最短路的差分约束系统模板

    • 我们再来看看输出格式:
    1. 如果从(1)(N)没有合法方案,则输出“(-1)

    2. 如果从(1)(N)的距离为无限大,则输出“(-2)

    3. 否则输出从(1)(N)的最大距离

    如果不好理解,可以转换成如下:

    1. 如果从(1)(N)存在环,则是“(-1)

    2. 如果(1)无法到达(N),则是“(-2)

    3. 否则输出从(1)(N)的最大距离

    • 好了,来看看上面思路编出来的代码(别急着说为什么A不了,因为还有(hack)在)

    PS:这里和下面的代码皆使用 (deque)(双端队列),这是 (SPFA)的一种叫做(SLF)的优化

    #include <bits/stdc++.h>
    using namespace std;
    deque<int> q;
    int n,ml,md,u,v,w,flag;
    int tot,dis[520010],vis[520010],cnt[520010],head[520010];
    
    struct node {
    	int to,net,val;
    } e[520010];
    
    inline void add(int u,int v,int w) {
    	e[++tot].to=v;
    	e[tot].val=w;
    	e[tot].net=head[u];
    	head[u]=tot;
    }
    
    inline void spfa() {
    	for(register int i=1;i<=n;i++) {
    		vis[i]=0;
    		dis[i]=2005020600;
    	}
    	dis[1]=0;
    	vis[1]=1;
    	cnt[1]=1;
    	q.push_back(1);
    	while(!q.empty()) {
    		int x=q.front();
    		q.pop_front();
    		vis[x]=0;
    		for(register int i=head[x];i;i=e[i].net) {
    			int v=e[i].to;
    			if(dis[v]>dis[x]+e[i].val) {
    				dis[v]=dis[x]+e[i].val;
    				if(cnt[v]==n) {
    					flag=1;
    					return ;
    				}
    				if(!vis[v]) {
    					vis[v]=1;
    					cnt[v]++;
    					if(!q.empty()&&dis[q.front()]<dis[v]) q.push_back(v);
    					else q.push_front(v);
    				}
    			}
    		}
    	}
    }
    
    int main() {
    	scanf("%d%d%d",&n,&ml,&md);
    	for(register int i=1;i<=ml;i++) {
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,w);
    	}
    	for(register int i=1;i<=md;i++) {
    		scanf("%d%d%d",&u,&v,&w);
    		add(v,u,-w);
    	}
    	spfa();
    	if(flag==1) puts("-1");
    	else {
    		if(dis[n]==2005020600) puts("-2");
    		else printf("%d",dis[n]);
    	}
    	return 0;
    }
    

    优化

    我们发现,最后三组(hack)数据过不了(可恶啊

    • 为什么?

    因为题目给出的数据并不保证图的连通性!

    • 什么意思?

    (1)有可能是“孤儿点”啊!那图就不连通了,结果就是上面的程序WA掉了

    • 怎么优化?

    我们就先特别跑一遍,判断图是否连通,如果连通就继续进行上面的操作;如果不连通就直接输出“(-1)”即可

    • 特别处理

    这里我们引入“超级源点”来帮助我们判断图的连通性

    即:建立一个点(0),然后与(1)(N)的每个点都连一条边权为(0)的边,这样我们就可以通过跑一遍额外的(SPFA)来判断图的连通性了(这也算作差分约束系统的一种基础操作吧)

    • 最后给出(100pts)(Code)
    #include <bits/stdc++.h>
    using namespace std;
    deque<int> q;
    int n,ml,md,u,v,w,flag;
    int tot,dis[520010],vis[520010],cnt[520010],head[520010];
    
    struct node {
    	int to,net,val;
    } e[520010];
    
    inline void add(int u,int v,int w) {
    	e[++tot].to=v;
    	e[tot].val=w;
    	e[tot].net=head[u];
    	head[u]=tot;
    }
    
    inline void spfa(int s) {
    	for(register int i=1;i<=n;i++) {
    		vis[i]=0;
    		dis[i]=2005020600;
    	}
    	dis[s]=0;
    	vis[s]=1;
    	cnt[s]=1;
    	q.push_back(s);
    	while(!q.empty()) {
    		int x=q.front();
    		q.pop_front();
    		vis[x]=0;
    		for(register int i=head[x];i;i=e[i].net) {
    			int v=e[i].to;
    			if(dis[v]>dis[x]+e[i].val) {
    				dis[v]=dis[x]+e[i].val;
    				if(cnt[v]==n) {
    					flag=1;
    					return ;
    				}
    				if(!vis[v]) {
    					vis[v]=1;
    					cnt[v]++;
    					if(!q.empty()&&dis[q.front()]<dis[v]) q.push_back(v);
    					else q.push_front(v);
    				}
    			}
    		}
    	}
    }
    
    int main() {
    	scanf("%d%d%d",&n,&ml,&md);
    	for(register int i=1;i<=n;i++) add(0,i,0);
    	for(register int i=1;i<=ml;i++) {
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,w);
    	}
    	for(register int i=1;i<=md;i++) {
    		scanf("%d%d%d",&u,&v,&w);
    		add(v,u,-w);
    	}
    	spfa(0);
    	if(flag==1) {
    		puts("-1");
    		return 0;
    	}
    	spfa(1);
    	if(flag==1) puts("-1");
    	else {
    		if(dis[n]==2005020600) puts("-2");
    		else printf("%d",dis[n]);
    	}
    	return 0;
    }
    

    最后,如果这篇题解有任何错误或您有任何不懂的,欢迎留言区评论啊,我会及时改正和回复,谢谢各位dalao啊qwq


  • 相关阅读:
    webpack安装、环境搭建和基本配置
    webpack知识点总结
    Vue之Vuex的使用
    vue之获取滚动条位置
    MongoDB ORM mongoose 配置和使用
    sequelize之通过options生成sql语句
    七牛上传之PutExtra的使用
    使用ssl-validator识别证书信息
    深入理解计算机系统(第三版)第八章重要内容摘要
    深入理解计算机系统(第三版)第七章重要内容摘要
  • 原文地址:https://www.cnblogs.com/Eleven-Qian-Shan/p/13233899.html
Copyright © 2011-2022 走看看