bzoj 2200: [Usaco2011 Jan]道路和航线——拓扑+dijkstra
Description
Input
Output
Sample Input
1 2 5
3 4 5
5 6 10
3 5 -100
4 6 -100
1 3 -10
样例输入解释:
一共六个城镇。在1-2,3-4,5-6之间有道路,花费分别是5,5,10。同时有三条航线:3->5,
4->6和1->3,花费分别是-100,-100,-10。FJ的中心城镇在城镇4。
Sample Output
NO PATH
5
0
-95
-100
样例输出解释:
FJ的奶牛从4号城镇开始,可以通过道路到达3号城镇。然后他们会通过航线达到5和6号城镇。
但是不可能到达1和2号城镇。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
const int M=3e4+,inf=0x3f3f3f3f;
int read(){
int ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
bool f=false;
int n,nr,np,S;
int first[M],cnt;
struct node{int to,next,w;}e[*M];
void ins(int a,int b,int w){e[++cnt]=(node){b,first[a],w}; first[a]=cnt;}
void insert(int a,int b,int w){ins(a,b,w); ins(b,a,w);}
int dis[M],vis[M];
int q[M],head,tail=;
void spfa(){
memset(dis,0x3f,sizeof(dis));
dis[S]=; vis[S]=;
q[head]=S;
while(head!=tail){
int x=q[head++]; if(head>M) head=;
for(int i=first[x];i;i=e[i].next){
int now=e[i].to;
if(dis[now]>dis[x]+e[i].w){
dis[now]=dis[x]+e[i].w;
if(!vis[now]){
vis[now]=;
if(dis[now]<=dis[q[head]]){
head--;
if(head<) head=M;
q[head]=now;
}
else{q[tail++]=now; if(tail>M) tail=;}
}
}
}
vis[x]=;
}
for(int i=;i<=n;i++)
if(dis[i]>=inf) printf("NO PATH\n");
else printf("%d\n",dis[i]);
}
int main(){
int x,y,w;
n=read(); nr=read(); np=read(); S=read();
for(int i=;i<=nr;i++) x=read(),y=read(),w=read(),insert(x,y,w);
for(int i=;i<=np;i++) x=read(),y=read(),w=read(),ins(x,y,w);
spfa();
return ;
}
当然正解是dijkstra +一波拓扑排序
因为负权边是有向且不存在能经过负权边的环 所以我们可以忽略航道
把图变成一个一个的颜色块
这样我们可以单独处理每个块的信息
至于为什么要拓扑 给个图吧
从S开始拓扑嘛 必须是所有指向一个块的前块都处理完才能处理当前块
当然像图中的红色点 如果正常的拓扑S所在的联通块入度就不为0了
而且实际上这两个块应该是无解的 我们要先处理这种情况
其实从S 开始dfs一波标记一下就好了
然后根据拓扑序每个块dijkstra就可以了(细节有点多QAQ
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
const int M=3e4+,inf=0x3f3f3f3f;
char buf[*M],*ptr=buf-;
int read(){
int ans=,f=,c=*++ptr;
while(c<''||c>''){if(c=='-') f=-; c=*++ptr;}
while(c>=''&&c<=''){ans=ans*+(c-''); c=*++ptr;}
return ans*f;
}
bool flag=false;
int n,nr,np,S;
int first[M],cnt;
struct node{int to,next,w;}e[*M];
void ins(int a,int b,int w){e[++cnt]=(node){b,first[a],w}; first[a]=cnt;}
void insert(int a,int b,int w){ins(a,b,w); ins(b,a,w);}
int color[M],hc;
void dfs(int x){
color[x]=hc;
for(int i=first[x];i;i=e[i].next){
int now=e[i].to;
if(!color[now]) dfs(now);
}
}
int sum,star[M];
struct pos{int from,to,next,w;}q[*M];
void insq(int a,int b,int w){q[++sum]=(pos){a,b,star[a],w}; star[a]=sum;}
int f[M],vis[M];
void find(int x){
vis[x]=f[color[x]]=n+;
for(int i=first[x];i;i=e[i].next){
int now=e[i].to;
if(!vis[now]) find(now);
}
}
int k,dis[M],wh[M],mark[*M];
struct QAQ{
int d,id;
bool operator <(const QAQ& x)const{return x.d<d;}
};
std::priority_queue<QAQ>qu[M];
std::queue<int>Q;
int in[M];
void find_w(int x){
vis[x]=k;
for(int i=star[x];i;i=q[i].next){
int now=color[q[i].to];
dis[q[i].to]=std::min(dis[q[i].to],dis[x]+q[i].w);
qu[now].push((QAQ){dis[q[i].to],q[i].to});
if(!--in[now]) Q.push(now);
}
for(int i=first[x];i;i=e[i].next)if(!mark[i]){
int now=e[i].to;
if(vis[now]!=k) find_w(now);
}
}
int main(){
fread(buf,,sizeof(buf),stdin);
int x,y,w;
n=read(); nr=read(); np=read(); S=read();
for(int i=;i<=nr;i++) x=read(),y=read(),w=read(),insert(x,y,w);
for(int i=;i<=n;i++)if(!color[i]) hc++,wh[hc]=i,dfs(i);
//for(int i=1;i<=n;i++) printf("[%d] ",color[i]); puts("");
for(int i=;i<=np;i++) x=read(),y=read(),w=read(),ins(x,y,w),mark[cnt]=,insq(x,y,w);
find(S); //for(int i=1;i<=hc;i++) printf("[%d]\n",f[i]);
memset(dis,0x3f,sizeof(dis)); dis[S]=;
for(int i=;i<=sum;i++) if(f[color[q[i].from]]&&f[color[q[i].to]]) in[color[q[i].to]]++;
//for(int i=1;i<=hc;i++) printf("[%d] ",in[i]); puts("");
Q.push(color[S]); qu[color[S]].push((QAQ){,S});
while(!Q.empty()){
int x=Q.front(); Q.pop(); k++;
while(!qu[x].empty()){
QAQ p=qu[x].top(); qu[x].pop();
if(dis[p.id]<p.d) continue;
for(int i=first[p.id];i;i=e[i].next)if(!mark[i]){
int now=e[i].to;
if(dis[now]>dis[p.id]+e[i].w) dis[now]=dis[p.id]+e[i].w,qu[x].push((QAQ){dis[now],now});
}
}
//printf("[%d]\n",x);
find_w(wh[x]);
}
for(int i=;i<=n;i++)
if(dis[i]>=inf) printf("NO PATH\n");
else printf("%d\n",dis[i]);
return ;
}
bzoj 2200: [Usaco2011 Jan]道路和航线——拓扑+dijkstra的更多相关文章
- [BZOJ 2200][Usaco2011 Jan]道路和航线 spfa+SLF优化
Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...
- BZOJ 2200: [Usaco2011 Jan]道路和航线
Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...
- bzoj 2200: [Usaco2011 Jan]道路和航线【spfa】
直接跑最短路就行了--还不用判负环 #include<iostream> #include<cstdio> #include<queue> using namesp ...
- 2200: [Usaco2011 Jan]道路和航线 (拓扑排序+dijstra)
Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...
- 【BZOJ】2200: [Usaco2011 Jan]道路和航线
[题意]给定n个点的图,正权无向边,正负权有向边,保证对有向边(u,v),v无法到达u,求起点出发到达所有点的最短距离. [算法]拓扑排序+dijkstra [题解]因为有负权边,直接对原图进行spf ...
- [Usaco2011 Jan]道路和航线
Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...
- bzoj2200: [Usaco2011 Jan]道路和航线
先忽略航线,求出图中所有连通块,再用航线拓扑排序求出每个连通块的优先级 然后dijkstra时优先处理优先级高的块里的点就行了 ps:这题SPFA会TLE #include <iostream& ...
- BZOJ 2200--[Usaco2011 Jan]道路和航线(最短路&拓扑排序)
2200: [Usaco2011 Jan]道路和航线 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1128 Solved: 414[Submit] ...
- BZOJ 2199: [Usaco2011 Jan]奶牛议会
2199: [Usaco2011 Jan]奶牛议会 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 375 Solved: 241[Submit][S ...
随机推荐
- Java 动态绑定和多态
动态绑定和多态 动态绑定是指:"在执行程序期间(而非编译期间),判断引用所指对象的实际类型,调用其相应的方法." 动态绑定(多态)存在的条件 要有继承. 要有重写. 父类引用指向子 ...
- 寒假学习计划——MOOC
课程 西安交通大学[https://www.icourse163.org/course/XJTU-46006?tid=1002265006] 理由 本身中国大学mooc里c++课程不多,完结了能够有很 ...
- iOS-Masonry用法
__weak typeof(self) weakSelf = self; UIView * tempView = [[UIView alloc]init]; NSInteger count = ;// ...
- Cacti自定义脚本,监测Docker信息(Script/Command方式)
一 环境背景 监控主机A:192.168.24.231:被监控主机B:192.168.24.233 A/B主机,通过公私钥建立ssh连接 [操作B主机时不需要输入密码,详见笔记:http://app. ...
- 文件传输底层是二进制 所以在传输前可以通过 InputStreamer 指定传输出的编码格式
文件传输底层是二进制 所以在传输前可以通过 InputStreamer 指定传输出的编码格式
- 第三方框架-纯代码布局:Masonry的简单使用
Masonry是一个对系统NSLayoutConstraint进行封装的第三方自动布局框架,采用链式编程的方式提供给开发者API.系统AutoLayout支持的操作,Masonry都支持,相比系统AP ...
- [洛谷P5169]xtq的异或和
题目大意:给你一张$n(n\leqslant10^5)$个点$m(m\leqslant3\times10^5)$条边的无向图,每条边有一个权值,$q(q\leqslant2^{18})$次询问,每次询 ...
- 详解利用ELK搭建Docker容器化应用日志中心
概述 应用一旦容器化以后,需要考虑的就是如何采集位于Docker容器中的应用程序的打印日志供运维分析.典型的比如SpringBoot应用的日志 收集.本文即将阐述如何利用ELK日志中心来收集容器化应用 ...
- BZOJ1596 [Usaco2008 Jan]电话网络 【树形dp】
题目链接 BZOJ1596 题解 先抽成有根树 设\(f[i][0|1][0|1]\)表示以\(i\)为根,儿子都覆盖了,父亲是否覆盖,父亲是否建塔的最少建塔数 转移一下即可 #include< ...
- 数组分组chunk的一种写法
lodash的_.chunk函数可以将数组按照数量分成若干组, 例如: const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; const groupByN ...