题目描述
漫长的一天结束了,饥困交加的奶牛们准备返回牛棚。
农场由 NN 片牧场组成(2\le N\le 5\times 10^42≤N≤5×10
4
),方便起见编号为 1\dots N1…N。所有奶牛都要前往位于牧场 NN 的牛棚。其他 片牧场中每片有一头奶牛。奶牛们可以通过 MM 条无向的小路在牧场之间移动(1\le M\le 10^51≤M≤10
5
)。第i条小路连接牧场 a_ia
i
和 b_ib
i
,通过需要时间 t_it
i
。每头奶牛都可以经过一些小路回到牛棚。
由于饥饿,奶牛们很乐于在他们回家的路上停留一段时间觅食。农场里有 KK 个有美味的干草捆,第 ii 个干草捆的美味值为 y_iy
i
。每头奶牛都想要在她回牛棚的路上在某一个干草捆处停留,但是她这样做仅当经过这个干草捆使她回牛棚的时间增加不超过这个干草捆的美味值。注意一头奶牛仅仅“正式地”在一个干草捆处因进食而停留,即使她的路径上经过其他放有干草捆的牧场;她会简单地无视其他的干草捆。
输入输出格式
输入格式:
输入的第一行包含三个空格分隔的整数 NN,MM 和 KK。以下 MM 行每行包含三个整数 a_ia
i
,b_ib
i
和 t_it
i
,表示牧场 a_ia
i
和 b_ib
i
之间有一条需要 t_it
i
时间通过的小路(a_ia
i
不等于 b_ib
i
,t_it
i
为不超过 10^410
4
的正整数)。
以下 KK 行,每行以两个整数描述了一个干草捆:该干草捆所在牧场的编号,以及它的美味值(一个不超过 10^910
9
的正整数)。同一片牧场中可能会有多个干草捆。
输出格式:
输出包含 N-1N−1 行。如果牧场 ii 里的奶牛可以在回牛棚的路上前往某一个干草捆并且在此进食,则第 ii 行为一个整数 11,否则为一个整数 00。
输入输出样例
输入样例#1:
4 5 1
1 4 10
2 1 20
4 2 3
2 3 5
4 3 2
2 7
输出样例#1:
1
1
1
说明
在这个例子中,牧场 33 里的奶牛可以停留进食,因为她回去的时间仅会增加 66(从 22 增加到 88),而这个增加量并没有超过干草捆的美味值 77。牧场 22 里的奶牛显然可以吃掉牧场 22 里的干草,因为这并不会导致她的最佳路径发生变化。对于牧场 11 里的奶牛是一个有趣的情况,因为看起来她的最佳路径(1010)可能会因为前去进食而有过大的增加量。然而,确实存在一条路径使得她可以前去干草捆处停留:先到牧场 44,然后去牧场 22(吃草),然后回到牧场 44。
题目链接
题意:
给你n-1头牛,分布在1到n-1上,m条边,现在n-1头牛要去n点,走最短路,但是路上k个点有艹,他们想吃艹在过去,但是又不愿意绕远路,只有当多走的路-艹的美味值小于等于原来要走的最短路的时候,他才会去吃艹,问你有多少头牛会去吃艹?
题解:
假设有一头牛到n的距离为a,到某个艹的距离为b,艹到n的距离为c,艹的美味值为k,那么牛会去吃艹的唯一可能就是a>=b+c-k,那么就是把c当做c-k再求一遍最短路呀。注意结束的条件就是当距离不能更短并且原来的点不吃草或者现在的点吃过艹了,否则都要加入队列。
#include<bits/stdc++.h>
using namespace std;
#define pa pair<int,int>
const int N=1e5+5,inf=2e9+7;
struct node
{
int to,next;
int val;
}e[N*2];
int head[N],cnt;
void add(int x,int y,int w)
{
e[cnt].to=y;
e[cnt].next=head[x];
e[cnt].val=w;
head[x]=cnt++;
}
int dis[N],n,m,k;
void dijkstra()
{
priority_queue<pa>Q;
dis[n]=0;
Q.push({0,n});
while(!Q.empty())
{
pa u=Q.top();
Q.pop();
if(-u.first!=dis[u.second])
continue;
for(int i=head[u.second];~i;i=e[i].next)
{
int v=e[i].to;
int w=e[i].val;
if(dis[v]>dis[u.second]+w)
{
dis[v]=dis[u.second]+w;
Q.push({-dis[v],v});
}
}
}
}
int vis[N];
int main()
{
scanf("%d%d%d",&n,&m,&k);
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
dis[i]=inf;
int x,y,w;
for(int j=1;j<=m;j++)
scanf("%d%d%d",&x,&y,&w),add(x,y,w),add(y,x,w);
dijkstra();
priority_queue<pa>Q;
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x,&w);
vis[x]=1;
dis[x]-=w;
Q.push({-dis[x],x});
}
while(!Q.empty())
{
pa u=Q.top();
Q.pop();
if(-u.first!=dis[u.second])
continue;
for(int i=head[u.second];~i;i=e[i].next)
{
int v=e[i].to;
int w=e[i].val;
if(dis[v]>dis[u.second]+w)
{
vis[v]=1;
dis[v]=dis[u.second]+w;
Q.push({-dis[v],v});
}
else if(dis[v]==dis[u.second]+w&&vis[u.second]&&!vis[v])
{
vis[v]=1;
Q.push({-dis[v],v});
}
}
}
for(int i=1;i<n;i++)
printf("%d\n",vis[i]);
return 0;
}