题目链接:https://www.luogu.com.cn/problem/P5960
题目中x1-x'1<=y1可以转变为
x1<=x'1+y1
换一下字母更显然易见:dis[v]<=dis[u]+edge[i].w
那么便可以转换成图上的最短路问题(解集),因为题中并没有说明是联通图,可以设一个超级源点,然后向每个节点连一条边权为0的边,然后从0点开始做最短路。
注意建边是从x'1连向x1。
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 int n,m,tot; 7 const int N=5005; 8 struct node{ 9 int to,next,w; 10 }edge[N<<1]; 11 int head[N],dis[N],vis[N],in[N]; 12 void add(int u,int v,int w){ 13 edge[tot].to=v; 14 edge[tot].next=head[u]; 15 edge[tot].w=w; 16 head[u]=tot++; 17 } 18 bool spfa(int u){ 19 queue<int> q; 20 q.push(u);vis[u]=1;dis[u]=0; 21 while(!q.empty()){ 22 u=q.front();q.pop();vis[u]=0; 23 if(in[u]==n) return 0; 24 for(int i=head[u];i!=-1;i=edge[i].next){ 25 int v=edge[i].to; 26 if(dis[v]>=dis[u]+edge[i].w){ 27 dis[v]=dis[u]+edge[i].w; 28 in[v]++; 29 if(!vis[v]){q.push(v);vis[v]=1;} 30 } 31 } 32 } 33 return 1; 34 } 35 int main(){ 36 memset(head,-1,sizeof(head)); 37 memset(dis,0x3f3f,sizeof(dis)); 38 scanf("%d%d",&n,&m); 39 for(int i=1;i<=m;i++){ 40 int u,v,w; 41 scanf("%d%d%d",&u,&v,&w); 42 add(v,u,w); 43 } 44 for(int i=1;i<=n;i++) add(0,i,0); 45 if(spfa(0)==0){printf("NO"); return 0;} 46 for(int i=1;i<=n;i++) printf("%d ",dis[i]); 47 return 0; 48 }