博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【枚举】【SPFA】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem I. Iron and Coal
阅读量:6868 次
发布时间:2019-06-26

本文共 2682 字,大约阅读时间需要 8 分钟。

那个人派出的队伍的行走的路径一定前半程是重合的,后半程分叉开来。

于是预处理每个点离1号点的最短路,到最近的铁的最短路,到最近的煤的最短路。(三次BFS / SPFA)然后枚举分岔点,尝试更新答案即可。

#include
#include
#include
#include
using namespace std;typedef long long ll;queue
q;int v[1000010],first[100010],next[1000010],en;ll ans=2147483647ll;void AddEdge(int U,int V){ v[++en]=V; next[en]=first[U]; first[U]=en;}int n,m,K,a[100010],b[100010],dis1[100010],dis2[100010],dis3[100010],eu[1000010],ev[1000010],es;bool inq[100010];void spfa1(int dis[]){ memset(dis,0x7f,sizeof(int)*100010); memset(inq,0,sizeof(inq)); for(int i=1;i<=m;++i){ dis[a[i]]=0; q.push(a[i]); inq[a[i]]=1; } while(!q.empty()) { int U=q.front(); for(int i=first[U];i;i=next[i]) if(dis[v[i]]>dis[U]+1) { dis[v[i]]=dis[U]+1; if(!inq[v[i]]) { q.push(v[i]); inq[v[i]]=1; } } q.pop(); inq[U]=0; }}void spfa2(int dis[]){ memset(dis,0x7f,sizeof(int)*100010); memset(inq,0,sizeof(inq)); for(int i=1;i<=K;++i){ dis[b[i]]=0; q.push(b[i]); inq[b[i]]=1; } while(!q.empty()) { int U=q.front(); for(int i=first[U];i;i=next[i]) if(dis[v[i]]>dis[U]+1) { dis[v[i]]=dis[U]+1; if(!inq[v[i]]) { q.push(v[i]); inq[v[i]]=1; } } q.pop(); inq[U]=0; }}void spfa3(int dis[]){ memset(dis,0x7f,sizeof(int)*100010); memset(inq,0,sizeof(inq)); dis[1]=0; q.push(1); inq[1]=1; while(!q.empty()) { int U=q.front(); for(int i=first[U];i;i=next[i]) if(dis[v[i]]>dis[U]+1) { dis[v[i]]=dis[U]+1; if(!inq[v[i]]) { q.push(v[i]); inq[v[i]]=1; } } q.pop(); inq[U]=0; }}int main(){// freopen("i.in","r",stdin); scanf("%d%d%d",&n,&m,&K); for(int i=1;i<=m;++i){ scanf("%d",&a[i]); } for(int i=1;i<=K;++i){ scanf("%d",&b[i]); } int x,y; for(int i=1;i<=n;++i){ scanf("%d",&x); for(int j=1;j<=x;++j){ scanf("%d",&y); AddEdge(y,i); eu[++es]=i; ev[es]=y; } } spfa1(dis1); spfa2(dis2); memset(first,0,sizeof(first)); memset(next,0,sizeof(next)); memset(v,0,sizeof(v)); en=0; for(int i=1;i<=es;++i){ AddEdge(eu[i],ev[i]); } spfa3(dis3); for(int i=1;i<=n;++i){ ans=min(ans,(ll)dis3[i]+(ll)dis1[i]+(ll)dis2[i]); } if(ans<=2000000000ll){ printf("%d\n",(int)ans); } else{ puts("impossible"); } return 0;}

转载于:https://www.cnblogs.com/autsky-jadek/p/7198397.html

你可能感兴趣的文章
linux查看哪些进程占用swap空间
查看>>
VS_断点无效
查看>>
关于“无敌删除命令”
查看>>
017 搭建eureka注册中心
查看>>
nis服务器搭建
查看>>
红帽企业存储管理之DRBD应用详解
查看>>
Linux下mail服务器架构之源码实现postfix邮件基本功能
查看>>
Bios加密
查看>>
Apache 服务+ AWStat分析系统的应用
查看>>
前端技术学习之选择器(六)
查看>>
使用 Docker 搭建 Tomcat 运行环境
查看>>
vim使用技巧
查看>>
牛反天望观测太阳系内目标的使用小记 (一)
查看>>
Create a RHEL6 PXE Installation Server
查看>>
【Android游戏开发二十二】(图文详解)游戏中灵活实现动画播放!
查看>>
桌面支持--Office2013没有Office Picture Manage怎么安装
查看>>
chmod修改文件权限失败
查看>>
数据结构与算法-->互为素数
查看>>
Linux系统学习方法——写给小白
查看>>
Nginx服务器报500 Internal Server Error错误
查看>>