题意:n个点,有m1条双向边,m2条单向边,双向边边长非负,单向边可能为负

保证如果有一条从x到y的单项边,则不可能存在从y到x的路径

问从S出发到其他所有点的最短路

n<=25000,n1,m2<=5e4,边权绝对值<=1e4

思路:听说银川出10年前USACO的原题?

负权边不能直接dijkstra,SPFA又会TLE

考虑这题的特殊限制:双向边边长非负,单向边可能为负,保证如果有一条从x到y的单向边,则不可能存在从y到x的路径

由此可知如果把所有联通性相同的点缩成一个分量,则负权的单向边只可能在不同的分量之间出现,且无负环

用并查集维护分量,将分量拓扑排序,按分量的拓扑序依次将边和点加入,跑dijkstra

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> Pll;
typedef vector<int> VI;
typedef vector<PII> VII;
//typedef pair<ll,ll>P;
#define N 300010
#define M 200010
#define fi first
#define se second
#define MP make_pair
#define pb push_back
#define pi acos(-1)
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
#define lowbit(x) x&(-x)
#define Rand (rand()*(1<<16)+rand())
#define id(x) ((x)<=B?(x):m-n/(x)+1)
#define ls p<<1
#define rs p<<1|1 const //ll MOD=1e9+7,inv2=(MOD+1)/2;
double eps=1e-;
int INF=1e9;
int dx[]={-,,,};
int dy[]={,,-,}; struct edge
{
int x,y,z;
edge()=default;
edge(int x,int y,int z):x(x),y(y),z(z){}
}a[N],b[N]; vector<edge>c[N];
vector<int>p[N];
int head[N],vet[N],nxt[N],len[N],flag[N],s[N],num[N],dis[N],vis[N],f[N],d[N],q[N],
tot,id,n,m1,m2,S; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} void add(int a,int b,int c)
{
nxt[++tot]=head[a];
vet[tot]=b;
len[tot]=c;
head[a]=tot;
} int find(int k)
{
if(f[k]!=k) f[k]=find(f[k]);
return f[k];
} void topo()
{
rep(i,,n) f[i]=i;
rep(i,,m1)
{
int p=find(a[i].x),q=find(a[i].y);
if(p!=q) f[p]=q;
}
rep(i,,n) head[i]=d[i]=;
tot=;
rep(i,,m2)
{
int p=find(b[i].x),q=find(b[i].y);
if(p!=q)
{
d[q]++; add(p,q,);
}
}
int t=,w=;
id=;
rep(i,,n)
if(f[i]==i&&d[i]==){w++; q[w]=i;}
while(t<w)
{
t++;
int u=q[t];
s[u]=++id;
int e=head[u];
while(e)
{
int v=vet[e];
d[v]--;
if(d[v]==){w++; q[w]=v;}
e=nxt[e];
}
}
rep(i,,n)
{
num[i]=s[find(i)];
p[num[i]].pb(i);
} rep(i,,m1)
{
int x=num[a[i].x];
c[x].pb(edge(a[i].x,a[i].y,a[i].z));
c[x].pb(edge(a[i].y,a[i].x,a[i].z));
}
rep(i,,m2)
{
int x=num[b[i].x];
c[x].pb(edge(b[i].x,b[i].y,b[i].z));
} } void solve()
{
priority_queue<PII> q;
rep(i,,n) head[i]=vis[i]=;
tot=;
rep(i,,n) dis[i]=INF;
dis[S]=;
rep(i,,id)
{
for(int j=;j<p[i].size();j++)
{
int x=p[i][j];
q.push(MP(-dis[x],x));
}
for(int j=;j<c[i].size();j++)
{
int x=c[i][j].x,y=c[i][j].y,z=c[i][j].z;
add(x,y,z);
} while(!q.empty())
{
int u=q.top().se;
q.pop();
if(vis[u]) continue;
vis[u]=;
int e=head[u];
while(e)
{
int v=vet[e];
if(dis[u]+len[e]<dis[v])
{
dis[v]=dis[u]+len[e];
if(num[v]<=i) q.push(MP(-dis[v],v));
}
e=nxt[e];
}
}
}
rep(i,,n)
if(dis[i]>5e8) printf("NO PATH\n");
else printf("%d\n",dis[i]);
} int main()
{
n=read(),m1=read(),m2=read(),S=read();
rep(i,,m1) a[i].x=read(),a[i].y=read(),a[i].z=read();
rep(i,,m2) b[i].x=read(),b[i].y=read(),b[i].z=read();
topo();
solve();
return ;
}

【BZOJ2200】道路和航线(并查集,拓扑排序,最短路)的更多相关文章

  1. 并查集+拓扑排序 赛码 1009 Exploration

    题目传送门 /* 题意:无向图和有向图的混合图判环: 官方题解:首先对于所有的无向边,我们使用并查集将两边的点并起来,若一条边未合并之前, 两端的点已经处于同一个集合了,那么说明必定存在可行的环(因为 ...

  2. HDU 1811:Rank of Tetris(并查集+拓扑排序)

    http://acm.hdu.edu.cn/showproblem.php?pid=1811 Rank of Tetris Problem Description   自从Lele开发了Rating系 ...

  3. hdu 1811Rank of Tetris (并查集 + 拓扑排序)

    /* 题意:这些信息可能有三种情况,分别是"A > B","A = B","A < B",分别表示A的Rating高于B,等于B ...

  4. 【并查集+拓扑排序】【HDU1811】【Rank of Tetris】

    题意:给你3种关系 A=B,A>B,A<B 问是否排名方式唯一,或者存在矛盾 解 1.读入数据先处理 =号 用并查集的祖先作为代表元素,其他儿子节点都等于跟这个点重叠. 再读入 '< ...

  5. Codeforces Round #541 (Div. 2) D(并查集+拓扑排序) F (并查集)

    D. Gourmet choice 链接:http://codeforces.com/contest/1131/problem/D 思路: =  的情况我们用并查集把他们扔到一个集合,然后根据 > ...

  6. Codeforces Round #541 (Div. 2) D 并查集 + 拓扑排序

    https://codeforces.com/contest/1131/problem/D 题意 给你一个n*m二维偏序表,代表x[i]和y[j]的大小关系,根据表构造大小分别为n,m的x[],y[] ...

  7. HDU 1811 Rank of Tetris(并查集+拓扑排序 非常经典)

    Rank of Tetris Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  8. HDU 1811(并查集+拓扑排序)题解

    Problem Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球.为了更好的符合那些爱好者的喜好,Lele又想了一个新点子:他 ...

  9. HDU 5222 ——Exploration——————【并查集+拓扑排序判有向环】

    Exploration Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  10. HDU——1272小希的迷宫(并查集+拓扑排序)

    小希的迷宫 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

随机推荐

  1. ubuntu 环境配置

    安装包准备 下载 410以上显卡驱动 文件名: NVIDIA-Linux-x86_64-410.66.run 下载 cuda 10.0 选择 CUDA Toolkit 10.0 (Sept 2018) ...

  2. java正则匹配正则表达式

    1.简单匹配小案例 public static void main( String[] args ){ // 按指定模式在字符串查找 String line = "This order wa ...

  3. input输入框的的input事件和change事件以及change和blur事件的区别

    input输入框的 oninput事件 ,在用户输入的时候触发,只要元素值发生变化就会触发 input输入框的 onchange事件 ,要在输入框失去焦点的时候触发事件,当鼠标在其他地方点击一下才会触 ...

  4. Java - Java Mail邮件开发(2)springboot +Java Mail + Html

    1.springboot + Java Mail + Html 项目结构: pom.xml <project xmlns="http://maven.apache.org/POM/4. ...

  5. 修改SpringBoot启动时的默认Banner图案

    1.在src/main/resources下新建banner.txt,在文件中加入要显示的图案即可: 2.生成图案的网站: http://patorjk.com/software/taag/ http ...

  6. C++编译器对属性的初始化检查远没有Java严格

    C++编译器对属性的初始化检查远没有Java严格// Java编译通过:class yy { public static void main(String[] args) { int i; Syste ...

  7. px-em-pt等字体的不同

  8. Spring boot项目集成Neo4j

    第一步,创建Springboot工程 使用Eclipse 创建Maven项目,并修改pom.xml文件为: <?xml version="1.0" encoding=&quo ...

  9. C#操作电脑多显示器设置

    电脑多显示器设置 第一种方式 通过使用api函数SetDisplayConfig来设置.这种方式在某些电脑中设置有几率会导致电脑黑屏 使用代码如下: private const uint SDC_AP ...

  10. 在Python中使用protobuf2.6.1 string format utf-8 and unicode error

    版本信息: protobuf: v2.6.1 python: 2.7 关于在Python中使用protobuf时 string格式字段的编码问题 在python中编码格式多采用utf-8格式.而pro ...