【Bzoj2330】【Scoi2011】糖果
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2330
这是一道比较裸的差分约束,这里求的是最小值,
建立一个超级原点0,跑spfa。
主要的点都在程序中,但是有几个注意点:
1.这里求的是最长路,可以 把边权都取负,就可以跑最短路,最后答案取负就可以了。
2.spfa判负环的时候,因为增加了一个超级原点,所以需要cnt[x]>=n+1才可以判定存在复还负环。
上程序:
1 #include<iostream>
2 #include<algorithm>
3 #include<queue>
4 #include<vector>
5 #define ll long long
6 using namespace std;
7 const int maxn=100007;
8 const ll inf=1LL<<29;
9 struct data{
10 int to,val;
11 };
12 vector <data> a[maxn];
13 int n,k,x,p,q;
14 ll ans=0,dis[maxn];
15 int cnt[maxn];
16 bool inq[maxn];
17 queue <int> que;
18 void add(int u,int v,int w){
19 data tmp;
20 tmp.to=v; tmp.val=w;
21 a[u].push_back(tmp);
22 }
23 bool spfa(int s){
24 que.push(0);
25 inq[0]=true;
26 cnt[0]=1;
27 dis[0]=0;
28 while (!que.empty()) {
29 int now=que.front();
30 que.pop();
31 inq[now]=false;
32 for (int i=0; i<a[now].size(); i++) {
33 int vv=a[now][i].to; int ww=a[now][i].val;
34 if (dis[now]+ww<dis[vv]) {
35 dis[vv]=dis[now]+ww;
36 if (!inq[vv]) {
37 que.push(vv);
38 inq[vv]=true;
39 ++cnt[vv];
40 if (cnt[vv]>n) return false;
41 }
42 }
43 }
44 }
45 return true;
46 }
47 int main(){
48 ios::sync_with_stdio(false);
49 cin>>n>>k;
50 fill(inq,inq+maxn,false);
51 fill(dis,dis+maxn,inf);
52 for (int i=1; i<=k; i++) {
53 cin>>x>>p>>q;
54 if (x==1) add(p,q,0),add(q,p,0);
55 if (x==2) add(p,q,-1);
56 if (x==3) add(q,p,0);
57 if (x==4) add(q,p,-1);
58 if (x==5) add(p,q,0);
59 }
60 for (int i=1; i<=n; i++) add(0,i,-1);
61 if (!spfa(0)) cout<<"-1"<<endl;
62 else {
63 for (int i=1; i<=n; i++) ans+=dis[i];
64 ans*=(-1);
65 cout<<ans<<endl;
66 }
67 return 0;
68 }