时间:2016-03-17 17:57:08 星期四
题目编号:[2016-03-17][HDU][1829][A Bug’s Life]
题目大意:
分析:扩点并查集
方法:
并查集分析:
- A 和 B 或者 A+n 和 B+n 在一组,表示A 和 B是同类
- A 和 B+n 在一组,表示如果A是雄性,则B是雌性
- B 和 A+n 在一组,表示如果B是雄性,则A是雌性
- 每组数据一个空行
- 方法2
#include <cstring>#include <cstdio>using namespace std;typedef long long LL;#define CLR(x,y) memset((x),(y),sizeof((x)))#define FOR(x,y,z) for(int (x)=(y);(x)<(z);++(x))const int maxn = 2000 + 100;int fa[maxn * 2];void ini(int n){ FOR(i,0,n + 1){ fa[i] = i; }}int fnd(int x){ return x == fa[x]?x:fa[x] = fnd(fa[x]);}int uni(int x,int y){ x = fnd(x); y = fnd(y); if(x == y) return 0; fa[x] = y; return 1;}int insame(int x,int y){ return fnd(x) == fnd(y);}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int T,cntcase = 0; scanf("%d",&T); while(T--){ int n,m,u,v,flg = 0; scanf("%d%d",&n,&m); ini((n + 1) * 2); FOR(i,0,m){ if(!flg){ scanf("%d%d",&u,&v); if(insame(u,v)){ flg = 1; }else { uni(u,v + n); uni(u + n,v); } }else scanf("%*d%*d"); } printf("Scenario #%d:\n",++cntcase); if(flg){ puts("Suspicious bugs found!\n"); }else puts("No suspicious bugs found!\n"); } return 0;}
方法2
带权并查集
分析
f(a,b) == 0,表示a和b同类
f(a,b)表示a和b的关系,则已知fa(a,b) fa(b,c),可以得到f(a,c) = (f(a,b),f(b,c))%2;
uni(int x,int y)中关系更新,已知f(x,y) = 0,f(x,fax),f(y,fay)那么f(fax,fay) = ((f(fax,x) + f(x ,y)%2) + f(y,fay))%2
方法:维护和父节点的关系,在find的时候压缩路径,最后得到的就是和祖宗节点的关系
- 注:刚开始第一个写成
((a+b)&1 + c) ,这是错误的,因为+的优先级比&高,会先计算 1 + c再且
#include <cstring>#include <cstdio>using namespace std;typedef long long LL;#define CLR(x,y) memset((x),(y),sizeof((x)))#define FOR(x,y,z) for(int (x)=(y);(x)<(z);++(x))const int maxn = 2000 + 100;int fa[maxn],relation[maxn];//relation[i] 表示i和父亲节点的关系,0表示同性,1表示异性void ini(int n){ CLR(relation,0); FOR(i,0,n + 1){ fa[i] = i; }}int fnd(int x){ if(x == fa[x]) return x; int tmp = fa[x]; fa[x] = fnd(fa[x]); relation[x] = (relation[tmp] + relation[x])&1 ; return fa[x]; }int uni(int x,int y){ int fax = fnd(x); int fay = fnd(y); if(fax == fay) return 0; fa[fax] = fay; //relation[fax] = (((relation[x]+1)&1) + relation[y])&1;//同余定理? relation[fax] = (relation[x] + 1 + relation[y])&1; return 1;}int isSame(int x,int y){ int fax = fnd(x); int fay = fnd(y); return fax == fay && relation[x] == relation[y]; }int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int T,cntcase = 0; scanf("%d",&T); while(T--){ int n,m,u,v,flg = 0; scanf("%d%d",&n,&m); ini(n); FOR(i,0,m){ if(!flg){ scanf("%d%d",&u,&v); if(isSame(u,v)){ flg = 1;continue; }else uni(u,v); }else scanf("%*d%*d"); } printf("Scenario #%d:\n",++cntcase); if(flg) puts("Suspicious bugs found!\n"); else puts("No suspicious bugs found!\n"); } return 0;}