【bzoj2330】 [SCOI2011]糖果
此题考察差分约束系统,用SPFA求最长路。
构图,边的权值只为0(等于 大于等于 小于等于)或1(大于 小于),dist数组存最长距离,即该小朋友的最少糖果数。
一次SPFA之后,直接输出dis数组总和,即为总糖果数。
注意事项:
1)由于等于是双向边,Node数组开两倍MAXN.
2)读入判断自环,用flag记录。
3)如果没有环,不可能有某个点dist大于n,若大于n则必为有环。
4)q中l与r取模。
5)答案总和可能大于int,开long long(WA 了好多次,调不出= =).
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> using namespace std; typedef long long LL; #define MAXN 100010 struct Node { int next,to,v; }e[MAXN<<2]; int cnt; int n,k; int x,a,b; LL sum; int l,r; int u,v,w; int num[MAXN]; int dist[MAXN],q[MAXN]; bool flag,vis[MAXN]; void link(int u,int v,int w) { cnt++; e[cnt].v=v; e[cnt].to=w; e[cnt].next=num[u]; num[u]=cnt; } int SPFA() { do { l++; u=q[l%MAXN]; if (dist[u]>n) return true; for (int i=num[u];i;i=e[i].next) { v=e[i].v; w=e[i].to; if (dist[u]+w>dist[v]) { dist[v]=dist[u]+w; if (!vis[v]) { r++; q[r%MAXN]=v; vis[v]=true; } } } vis[u]=false; }while(l<r); return false; } int main() { scanf("%d%d",&n,&k); for (int i=1;i<=k;i++) { scanf("%d%d%d",&x,&a,&b); switch(x) { case 1: link(a,b,0); link(b,a,0); break; case 2: if (a==b) flag=true; link(a,b,1); break; case 3: link(b,a,0); break; case 4: if (a==b) flag=true; link(b,a,1); break; case 5: link(a,b,0); break; } } for (int i=1;i<=n;i++) { q[++r]=i; dist[i]=1; vis[i]=true; } if (flag || SPFA()) { printf("-1\n"); return 0; } for (int i=1;i<=n;i++) sum+=dist[i]; printf("%lld",sum); return 0; }