[2019.1.1]BZOJ4195 [Noi2015]程序自動分析
阿新 • • 發佈:2019-03-17
沒有 維護 很難 span 約束 spa i++ while --
首先很容易想到並查集維護,將相等的數merge起來。但是我們很難維護不等的情況。
那怎麽辦?
我們發現我們可以查詢兩數不等是否成立,只是不能維護它而已,並且事實上,不等沒有類似\(a\ne b,b\ne c,\texttt{則}a\ne c\)的性質。
所以我們可以變更維護順序。
先在並查集裏維護等於的關系(也就是先處理\(e=1\)的約束),然後對於每一個不等約束條件\(a\ne b\),判斷\(a,b\)是否在同一並查集裏。
至於數據範圍是\(10^9\),開個map把每一個出現的未知數編號對應到\([1,n]\)範圍內的整數上就好了。
code:
#include<bits/stdc++.h> using namespace std; int T,n,u,v,cnt,tu,tv,op,ne[100010][2],sz,f[200010]; map<int,int>mp; int getf(int x){ return f[x]==x?x:f[x]=getf(f[x]); } void merge(int x,int y){ if(getf(x)==getf(y))return; f[f[x]]=f[y]; } int main(){ scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=1;i<=2*n;i++)f[i]=i; mp.clear(); cnt=0; sz=0; for(int i=1;i<=n;i++){ scanf("%d%d%d",&u,&v,&op); tu=mp[u]; if(!tu)tu=mp[u]=++cnt; tv=mp[v]; if(!tv)tv=mp[v]=++cnt; if(!op)ne[++sz][0]=tv,ne[sz][1]=tu; else merge(tu,tv); } for(int i=1;i<=cnt;i++)getf(i); for(int i=1;i<=sz;i++) if(f[ne[i][0]]==f[ne[i][1]]){ puts("NO"); goto END; } puts("YES"); END: ; } return 0; }
[2019.1.1]BZOJ4195 [Noi2015]程序自動分析