洛谷3275 & BZOJ2330:[SCOI2011]糖果——题解
https://www.luogu.com.cn/problem/P3275
https://www.lydsy.com/JudgeOnline/problem.php?id=2330
幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。
当差分约束练习……个鬼啊怎么还要缩点的啊。
先按照正常的差分约束建图,别忘了为了保证每个孩子都要有糖于是多来一个点,所有的点连向它边权为-1……不对啊这图怎么建完了没法构造能够通向所有点的起点,以及边要么是0要么是-1怎么做啊……
把所有边反过来的同时边权取相反数,变成求最长路(然后就可以看到题解区一堆牛鬼蛇神般玄学求最长路的方法……比较无语)
首先把0边单独提出来缩一波点,然后再把所有的边提出来拓扑排序一下的同时更新dis,如果搜完了发现不是DAG答案就是-1,否则答案就是dis*缩的点数。
别忘了读入的时候也要特判无解的情况。
#include<cmath> #include<stack> #include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=1e5+5; const int M=5e5+5; const int INF=1e9; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct node{ int u,v,w,nxt; }e[2][M]; int cnt,h[2][N],indeg[N]; inline void add(int u,int v,int w,int k){ e[k][++cnt].u=u;e[k][cnt].v=v;e[k][cnt].w=w; e[k][cnt].nxt=h[k][u];h[k][u]=cnt; if(k)indeg[v]++; } int dfn[N],low[N],to[N],sum[N],t,l; stack<int>q; bool inq[N],vis[N]; void tarjan(int u){ int v; dfn[u]=low[u]=++t; q.push(u);inq[u]=1; for(int i=h[0][u];i;i=e[0][i].nxt){ v=e[0][i].v; if(e[0][i].w)continue; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); }else if(inq[v]){ low[u]=min(low[u],dfn[v]); } } if(dfn[u]==low[u]){ l++; do{ v=q.top(); q.pop(); inq[v]=0; to[v]=l; sum[l]++; }while(v!=u); } } int n,k; ll ans,dis[N]; queue<int>p; bool topu(){ int tot=0; for(int i=1;i<=l;i++){ if(!indeg[i])p.push(i); } while(!p.empty()){ int u=p.front();p.pop();++tot; ans+=dis[u]*sum[u]; for(int i=h[1][u];i;i=e[1][i].nxt){ int v=e[1][i].v,w=e[1][i].w; indeg[v]--; if(!indeg[v])p.push(v); dis[v]=max(dis[v],dis[u]+w); } } return tot==l; } int main(){ n=read(),k=read(); for(int i=1;i<=n;i++)add(0,i,1,0); for(int i=1;i<=k;i++){ int x=read(),u=read(),v=read(); if((x==2||x==4)&&u==v){ puts("-1"); return 0; } if(x==1)add(u,v,0,0),add(v,u,0,0); if(x==2)add(u,v,1,0); if(x==3)add(v,u,0,0); if(x==4)add(v,u,1,0); if(x==5)add(u,v,0,0); } for(int i=0;i<=n;i++){ if(!dfn[i])tarjan(i); } int tmp=cnt;cnt=0; for(int i=1;i<=tmp;i++){ int u=e[0][i].u,v=e[0][i].v,w=e[0][i].w; if(to[u]==to[v]){ if(w){ puts("-1"); return 0; } }else add(to[u],to[v],w,1); } if(!topu())puts("-1"); else printf("%lld\n",ans); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++