【scoi2011】糖果 P2242
阿新 • • 發佈:2018-11-30
Description
幼兒園裡有N個小朋友,lxhgww老師現在想要給這些小朋友們分配糖果,要求每個小朋友都要分到糖果。但是小朋友們也有嫉妒心,總是會提出一些要求,比如小明不希望小紅分到的糖果比他的多,於是在分配糖果的時候,lxhgww需要滿足小朋友們的K個要求。幼兒園的糖果總是有限的,lxhgww想知道他至少需要準備多少個糖果,才能使得每個小朋友都能夠分到糖果,並且滿足小朋友們所有的要求。
Input
第一行是兩個整數N,K。接下來K行,表示這些點需要滿足的關係,每行3個數字,X,A,B。如果X=1,表示第A個小朋友分到的糖果必須和第B個小朋友分到的糖果一樣多;如果X=2,表示第A個小朋友分到的糖果必須少於第B個小朋友分到的糖果;如果X=3,表示第A個小朋友分到的糖果必須不少於第B個小朋友分到的糖果;如果X=4,表示第A個小朋友分到的糖果必須多於第B個小朋友分到的糖果;如果X=5,表示第A個小朋友分到的糖果必須不多於第B個小朋友分到的糖果。
Output
輸出一行,表示lxhgww老師至少需要準備的糖果數,如果不能滿足小朋友們的所有要求,就輸出-1。
Hint
對於30%的資料,保證 N<=100。對於100%的資料,保證 N<=100000。對於所有的資料,保證 K<=100000,1<=X<=5,1<=A,B<=N
Solution
詳見男朋友的題解。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<stack> #include<queue> #define maxn 200005 #define int long long using namespace std; struct Edge{ int u; int v; int w; int next; }edge[maxn],edge2[maxn]; stack<int>stk; int first[maxn],last[maxn],dfn[maxn],low[maxn],belong[maxn],first2[maxn],last2[maxn],rd[maxn],dp[maxn]; int node,x,y,z,dfn_TimeClock,cnt,node2,ans,n,m; void addedge(int u,int v,int w){ edge[++node]=(Edge){u,v,w,0}; if(first[u]==0)first[u]=node; else edge[last[u]].next=node; last[u]=node; } void addedge2(int u,int v,int w){ edge2[++node2]=(Edge){u,v,w,0}; if(first2[u]==0)first2[u]=node2; else edge2[last2[u]].next=node2; last2[u]=node2; } void init(){ scanf("%lld%lld",&n,&m); for(int i=1;i<=m;i++){ scanf("%lld%lld%lld",&x,&y,&z); if(x==1){ addedge(y,z,0); addedge(z,y,0); } else if(x==2){ addedge(y,z,1); } else if(x==3){ addedge(z,y,0); } else if(x==4){ addedge(z,y,1); } else if(x==5){ addedge(y,z,0); } } } void tarjan(int s){ dfn[s]=low[s]=++dfn_TimeClock; stk.push(s); for(int q=first[s];q;q=edge[q].next){ int j=edge[q].v; if(dfn[j]==0){ tarjan(j); low[s]=min(low[s],low[j]); } else if(!belong[j]){ low[s]=min(low[s],dfn[j]); } } if(low[s]==dfn[s]){ cnt++; belong[s]=cnt; while(stk.top()!=s){ belong[stk.top()]=cnt; stk.pop(); } stk.pop(); } } void toposort(){ queue<int>p; for(int i=1;i<=cnt;i++){ if(rd[i]==0){ p.push(i); dp[i]=1; } } while(!p.empty()){ int t=p.front(); p.pop(); rd[t]=0; for(int q=first2[t];q;q=edge2[q].next){ int j=edge2[q].v; dp[j]=max(dp[j],dp[t]+edge2[q].w); if(rd[j]>1)rd[j]--; else p.push(j); } } } signed main(){ init(); for(int i=1;i<=n;i++){ if(!dfn[i])tarjan(i); } for(int i=1;i<=n;i++){ for(int p=first[i];p;p=edge[p].next){ int j=edge[p].v; if(belong[i]!=belong[j]||edge[p].w==1){ rd[belong[j]]++; addedge2(belong[i],belong[j],edge[p].w); } } } toposort(); for(int i=1;i<=cnt;i++){ if(rd[i]!=0){ printf("-1"); return 0; } } for(int i=1;i<=n;i++){ ans+=dp[belong[i]]; } printf("%lld\n",ans); return 0; }