益智游戏
题目描述
小P 和小R 在玩一款益智游戏。游戏在一个正权有向图上进行。 小P 控制的角色要从A 点走最短路到B 点,小R 控制的角色要从C 点走最短路到D 点。 一个玩家每回合可以有两种选择,移动到一个相邻节点或者休息一回合。 假如在某一时刻,小P 和小R 在相同的节点上,那么可以得到一次特殊奖励,但是在每 个节点上最多只能得到一次。 求最多能获得多少次特殊奖励
输入
第一行两个整数n,m 表示有向图的点数和边数。 接下来m 行每行三个整数xi,yi,li,表示从xi 到yi 有一条长度为li 的边。 最后一行四个整数A,B,C,D,描述小P 的起终点,小R 的起终点。
输出
输出一个整数表示最多能获得多少次特殊奖励。若小P 不能到达B 点或者小R 不能到达 D 点则输出-1。
样例输入
5 5
1 2 1
2 3 2
3 4 4
5 2 3
5 3 5
1 3 5 4
样例输出
2
提示
对于30%的数据,满足n≤50
对于60%的数据,满足n≤1000,m≤5000
对于100%的数据,满足n≤50000,m≤200000,1≤li≤500000000
如果dist[s][u]+w(u,v)+dist[v][t]==mindist,那么(u,v)这条有向线段就一定在最短路的路径上
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define MAXN 50000
#define MAXM 200000
#define INF 2147483647
struct node{
int v,w;
node *next;
}edge[3][MAXM+10],*adj[3][MAXN+10],*ecnt[3]={&edge[0][0],&edge[1][0]};
node _edge[MAXM+10],*_adj[MAXN+10],*_ecnt=&_edge[0];
int n,m,s[3],t[3],ds[3][MAXN+10],dt[3][MAXN+10],indegree[MAXN+10],f[MAXN+10];
int ans;
bool vis[MAXN+10];
struct list{
int v,w;
list(){}
list(int a,int b){
v=a,w=b;
}
};
bool operator < (list a,list b){
return a.w>b.w;
}
priority_queue<list> que;
void addedge(int u,int v,int w)
{
node *p=++ecnt[0];
p->v=v,p->w=w;
p->next=adj[0][u];
adj[0][u]=p;
p=++ecnt[1];
p->v=u,p->w=w;
p->next=adj[1][v];
adj[1][v]=p;
}
void add_edge(int u,int v)
{
node *p=++_ecnt;
p->v=v;
p->next=_adj[u];
_adj[u]=p;
}
void read()
{
int x,y,w;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&w);
addedge(x,y,w);
}
scanf("%d%d%d%d",&s[0],&t[0],&s[1],&t[1]);
}
void dijkstra(int k,int st,int d[])
{
for(int i=1;i<=n;i++)
d[i]=INF,vis[i]=true;
d[st]=0;
que.push(list(st,0));
while(!que.empty()){
int u=que.top().v;
que.pop();
if(!vis[u]) continue;
vis[u]=false;
for(node *p=adj[k][u];p;p=p->next){
int v=p->v,w=p->w;
if(d[v]>d[u]+w){
d[v]=d[u]+w;
que.push(list(v,d[v]));
}
}
}
}
void Get_mxlen() //like a SPFA
{
//use toposort to make the work run more quickly
//有向无环图
memset(f,0,sizeof f);
queue<int> qq;
for(int i=1;i<=n;i++)
if(!indegree[i])
qq.push(i),f[i]=1;
while(!qq.empty()){
int u=qq.front();
qq.pop();
ans=max(ans,f[u]);
for(node *p=_adj[u];p;p=p->next){
int v=p->v;
f[v]=max(f[v],f[u]+1);
indegree[v]--;
if(!indegree[v]) qq.push(v);
}
}
}
int main()
{
read();
dijkstra(0,s[0],ds[0]);
dijkstra(1,t[0],dt[0]);
dijkstra(0,s[1],ds[1]);
dijkstra(1,t[1],dt[1]);
if(ds[0][t[0]]==INF || ds[1][t[1]]==INF){
printf("-1\n");
return 0;
}
for(int u=1;u<=n;u++){
for(node *p=adj[0][u];p;p=p->next){
int v=p->v,w=p->w;
if(ds[0][u]==INF || dt[0][v]==INF || ds[1][v]==INF || dt[1][u]==INF)
continue;
if(ds[0][u]+w+dt[0][v]==ds[0][t[0]] && ds[1][u]+w+dt[1][v]==ds[1][t[1]]){
add_edge(u,v);
indegree[v]++;
}
}
}
Get_mxlen();
printf("%d\n",ans);
return 0;
}
浙公网安备 33010602011771号