题意: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. 【Linux开发】计算机底层是如何访问显卡的?

    1. 显卡驱动是怎么控制显卡的, 就是说, 使用那些指令控制显卡, 通过端口么? 2. DirectX 或 OpenGL 或 CUDA 或 OpenCL 怎么找到显卡驱动, 显卡驱动是不是要为他们提供 ...

  2. webView实现网页缩放

    项目中遇到要实现webview上面的网页缩放功能,在网上查了资料加自己实践后得出结论: //缩放开关,设置此属性,仅支持双击缩放,不支持触摸缩放 mWebView.getSettings().setS ...

  3. Java第四周总结+实验报告

    实验二 Java简单类与对象 实验目的 掌握类的定义,熟悉属性.构造函数.方法的作用,掌握用类作为类型声明变量和方法返回值: 理解类和对象的区别,掌握构造函数的使用,熟悉通过对象名引用实例的方法和属性 ...

  4. tarjan算法应用 割点 桥 双连通分量

    tarjan算法的应用. 还需多练习--.遇上题目还是容易傻住 对于tarjan算法中使用到的Dfn和Low数组. low[u]:=min(low[u],dfn[v])--(u,v)为后向边,v不是u ...

  5. 【系统】win10锁屏后,护眼绿自动恢复解决

    针对自己电脑(其他人的不晓得),win10锁屏后,重新登录,护眼绿会自动恢复成白色,查询资料需要修改注册表两个地方: 1.计算机\HKEY_CURRENT_USER\Control Panel\Col ...

  6. 安装Pycharm(方便编辑代码的IDE(编辑器))以及 使用Pycharm新建项目

    安装Pycharm(方便编辑代码的IDE(编辑器))以及 使用Pycharm新建项目 一.下载安装Pycharm 首先要下载Pycharm这个软件,官网的下载地址是: http://www.jetbr ...

  7. Kotlin学习(4)Lambda

    Lanbda基础 /* *Lambda允许把代码块当作参数传递给函数 */ fun a(plus:(Int,Int)->Unit){ plus(,) //声明函数的地方,调用代码块,在这里传参 ...

  8. author认证模块

    author认证模块 用auth模块 你就用全套 不是自己写一部分 用别人一部分 ​ 创建超级管理员,用于登录DJango admin的后台管理 ​ 命令:createsuperuser,输入顺序用户 ...

  9. vue+element ui 时间格式化

    <el-table-column prop="startTime" label="日期" width="200" align=&quo ...

  10. Tomcat报java.io.IOException: Broken pipe错误

    Tomcat报java.io.IOException: Broken pipe错误,如下图: 解决方案:我的原因是因为网络策略导致出现该问题,即网络端口未启用或被限制.