Codeforces 1012B Chemical table (思维+二分图)
<题目链接>
题目大意:
给定一个n*m的矩阵网格,向其中加点,对于一个组成矩形的四个点中如果有三个点中有元素,那么第四个点中会自动产生新的元素。问你最少再加多少个点能够填满这个网格。
解题分析:
不是很好想,先将行列看成两个集合,每次加点操作,就相当于x集合向y集合连了一条边。
本题可以巧妙的转化为,要使x和y集合所有的点都连通最少需要添加几条边。初始情况需要n+m-1条边(因为两个集合有n+m个点,且相同集合不能连边)。
然后根据题目已经给出的边判断最终的连通块个数,用并查集来判连通。主要是这个转化的思想不好想。
#include <bits/stdc++.h> using namespace std; template<typename T> inline void read(T&x){ x=0;int 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(); } x*=f; } #define REP(i,s,t) for(int i=s;i<=t;i++) const int N = 2e5+5; int fa[N<<1]; int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); } inline bool merge(int x,int y){ int f1=find(x),f2=find(y); if(f1!=f2){ fa[f1]=f2;return true;} return false; } int main(){ int n,m,q; read(n);read(m);read(q); REP(i,0,n+m)fa[i]=i; int ans=n+m-1; //其实就是最少用多少条边,使得这n+m个点连通,最多只需要用n+m-1条 REP(i,1,q){ int a,b;read(a);read(b); b+=n; if(merge(a,b))ans--; //如果这条边有效,则需要的边数-- } cout<<ans<<endl; }
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。