易爆物
| 易爆物D305 | 
| 运行时间限制:1000ms; 运行空间限制:51200KB | 
| 试题描述 | 
| 有一些简单化合物,每个化合物部由两种元素组成的(每个元素用一个大写字母表示)。你是一个装箱工人,从实验员那里按照顺序依次把一些简单化合物装到车上。但这里存在一个安全隐患:如果车上存在k个简单化合物,正好包含k种元素,那么它们将组成一个易爆的混合物。为了安全起见,每当你拿到一个化合物时,如果它和已装车的化合物形成易爆混合物,你就应当拒绝装车;否则就应该装车。编程输出有多少个没有装车的化合物。 | 
| 输入 | 
| 第一行包含一个正整数n,表示化合物的个数。接下来有n行,每行包括两个不同的整数a和b,表示一个由元素a和元素b组成的简单化合物。所有简单化合物按照交给你的先后顺序排列。 | 
| 输出 | 
| 一个数,表示没有装车的化合物的个数。 | 
| 输入示例 | 
| 6 | 
| 输出示例 | 
| 2 | 
| 其他说明 | 
| 数据范围:0 <= a,b <= 10^5 UVA1160 | 
---------------------------------------------------------------------------------------------------------------------------------
讲解:
本题要求了装车顺序,这样这道题就变得so easy。
首先,题说的有点绕:“如果车上存在k个简单化合物,正好包含k种元素,那么它们将组成一个易爆的混合物。”这句话可能很多读者不明白,但这也是解题的思路:把每一个元素看成一个点,那么每一个简单化合物就是连接两个点的边。这样对于易爆物的定义就出来了。在一堆点中有许多遍连接两个点,当连接某一条边时,此图出现回路时这条边就不能连接(组成易爆物)。
这样,这道题就变成赤裸裸的并查集(元素是否在这个集合中)。
代码实现(如果看不懂(着急约会),跳过这个代码):
 
#include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<cstdio> using namespace std; struct union_find_set//并查集 { int father[100010],n; void create(int k) { n=k; for(int i=1;i<=n;i++) father[i]=i; return; }//建立并查集,初始化 int finds(int x) { if(father[x]==x) return x; return father[x]=finds(father[x]);//压缩路径 //return father[x]=father[x]==x?x:finds(father[x]); //装逼专用 }//寻找祖先 bool unions(int x,int y) { int t1=finds(x),t2=finds(y); if(t1==t2) return false; father[t2]=t1; return true; }//合并 /*int size() { int ans=0,i; for(i=1;i<=n;i++) if(father[i]==i) ans++; return ans; }*/ //查找集合的个数 //本题不需要 }; int main() { int i,x,y,n,ans=0; union_find_set f; scanf("%d",&n); f.create(100010); for(i=1;i<=n;i++) { scanf("%d%d",&x,&y); if(!f.unions(x,y)) ans++;//如果不装车,ans++ } cout<<ans; return 0; }
换一种编者喜欢的代码:
 
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int n,ans,a,b,f[100005]; int gets(int x1) { if(f[x1]==x1) return x1; f[x1]=gets(f[x1]); return f[x1]; } void h(int x,int y) { int f1=gets(x),f2=gets(y); if(f1==f2) ans++; else f[f1]=f2; } int main() { int i; scanf("%d",&n); for(i=1;i<=100010;i++) f[i]=i; for(i=1;i<=n;i++) scanf("%d%d",&a,&b),h(a,b); printf("%d",ans); return 0; }

 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号