洛谷 P5960 【模板】差分约束算法(差分约束)

题目链接: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 }
AC代码

 

posted @ 2020-07-31 19:02  dfydn  阅读(154)  评论(0编辑  收藏  举报