洛谷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/+

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2020-02-03 13:19  luyouqi233  阅读(134)  评论(0编辑  收藏  举报