Codeforces 1209D Cow and Snacks(并查集)

    技术2022-07-13  74

    传送门

    题意:有n个点心,m个客人,每个客人有两个喜欢的点心,现需要给客人安排一定顺序,每轮到一个人,他吃掉所有剩下的他喜欢的点心(有一个吃一个,有俩吃俩)。一个都吃不到的人就会伤心。请问合理安排后最小的伤心人数是多少。

    题解:我们需要尽可能平均分配,就让每个人尽可能只吃一个(可以理解为重复利用一些点心?A吃了1,2,B吃了2,3相当于2利用了两次)。于是灵光乍现想到把每个客人看成一条边然后跑个最长路之类的东西?后来细想一下发现不对,如果这么建图,一个人会伤心当且仅当这条边两端已经被连通过,所以应该用并查集来搞。于是直接跑一个并查集,merge的时候如果两个点已经在同一个连通图则ans++,就完了。

    感觉这种建图还是相当创新的一波操作,能做到这样的题也算是意外收获₍ ᐢ. ̫ .ᐢ ₎

    ​​​

    #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=1e5+4; int n,m; int fa[N]; int ans; inline int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x*f; } inline int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } inline void merge(int u,int v) { int fu=find(u),fv=find(v); if (fu^fv) { fa[fu]=fv; } else ++ans; } int main() { n=read(),m=read(); for (register int i=1;i<=n;++i) fa[i]=i; for (register int i=0;i<m;++i) { int u=read(),v=read(); merge(u,v); } cout<<ans<<endl; return 0; }

     

    Processed: 0.022, SQL: 9