蓝书3.4 差分约束系统

T1 糖果 bzoj 2330

题目大意:

幼儿园里有N个小朋友,给这些小朋友们分配糖果,要求每个小朋友都要分到糖果 每个小朋友会提出一些要求

K行 每行输入三个数X A B

如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多

如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果

如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果

如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果

如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果

思路:

一道裸题

对于X=1的情况 在a b之间连无向边权值为0

X=2和X=4 在从a->b||b->a连有向边权值为1

X=3和X=5 在从b->a||a->b连有向边权值为0

如果有正环输出-1 开始的时候将所有点都放到队列里

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2147483647
10 #define ll long long
11 #define MAXN 100100
12 #define eps 1e-9
13 using namespace std;
14 inline int read()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
19     return x*f;
20 }
21 int n,m,q[MAXN<<4],l=1,r,f,st,inq[MAXN],num[MAXN];
22 ll ans;
23 int to[MAXN<<1],nxt[MAXN<<1],fst[MAXN],dis[MAXN],val[MAXN<<1],cnt;
24 void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
25 int spfa()
26 {
27     int x;
28     while(l<=r)
29     {
30         x=q[l++],inq[x]=0;
31         for(int i=fst[x];i;i=nxt[i])
32             if(dis[to[i]]<dis[x]+val[i])
33             {
34                 dis[to[i]]=dis[x]+val[i];
35                 if(!inq[to[i]]) q[++r]=to[i],inq[to[i]]=1;
36                 if(++num[to[i]]>=n) return 0;
37             }
38     }
39     return 1;
40 }
41 int main()
42 {
43     n=read(),m=read();int c,a,b;
44     while(m--)
45     {
46         c=read(),a=read(),b=read();
47         if(c==1) {add(a,b,0);add(b,a,0);}
48         if(c==2) if(a!=b) add(a,b,1);else {puts("-1");return 0;}
49         if(c==3) add(b,a,0);
50         if(c==4) if(a!=b) add(b,a,1);else {puts("-1");return 0;}
51         if(c==5) add(a,b,0);
52     }
53     for(int i=1;i<=n;i++) dis[i]=1,inq[i]=1,num[i]=1,q[++r]=i;
54     if(!spfa()) {puts("-1");return 0;}
55     for(int i=1;i<=n;i++) ans+=dis[i];
56     printf("%lld",ans);
57 }
58 
View Code

T2 Layout bzoj 1731

题目大意:

数轴上放一些点 按顺序放n个点

有一些条件为 点a与点b的距离不大于或不小于一个距离c

思路:

还是裸题 

因为按顺序放

所以不小于的情况就从a->b连权值为c的边 不大于的情况从b->a连权值为-c的边

判负环

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2139062143
10 #define ll long long
11 #define MAXN 100100
12 #define eps 1e-9
13 using namespace std;
14 inline int read()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
19     return x*f;
20 }
21 int n,m1,m2,q[MAXN<<4],l=1,r,f,st,inq[MAXN],num[MAXN];
22 ll ans;
23 int to[MAXN<<1],nxt[MAXN<<1],fst[MAXN],dis[MAXN],val[MAXN<<1],cnt;
24 void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
25 ll spfa()
26 {
27     q[++r]=1,dis[1]=0,num[1]=1;int x;
28     while(l<=r)
29     {
30         x=q[l++],inq[x]=0;
31         for(int i=fst[x];i;i=nxt[i])
32             if(dis[to[i]]>dis[x]+val[i])
33             {
34                 dis[to[i]]=dis[x]+val[i];
35                 if(!inq[to[i]]) q[++r]=to[i],inq[to[i]]=1;
36                 if(++num[to[i]]>=n) return -1;
37             }
38     }
39     if(dis[n]==inf) return -2;
40     return dis[n];
41 }
42 int main()
43 {
44     n=read(),m1=read(),m2=read();int a,b,c;
45     while(m1--){a=read(),b=read(),c=read();add(a,b,c);}
46     while(m2--){a=read(),b=read(),c=read();add(b,a,-c);}
47     memset(dis,127,sizeof(dis));
48     printf("%lld",spfa());
49 }
View Code
原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9369823.html