破坏城市
时间限制:1000 ms | 内存限制:65535 KB
难度:3
描述
-
L 是一个坏蛋,他总是破坏遇见的一切事情。
一天,L到达一个新的城市,该城市有n个点,有m条线路来连接这n个点。L将破坏所有的线路。但是他想知道当他破坏前i条线路时该城市有多少个块组成。我们认为当两个点可以通过线路直接或间接相互到达时,这两点属于同一个块
L 是一个坏蛋,他总是破坏遇见的一切事情。
一天,L到达一个新的城市,该城市有n个点,有m条线路来连接这n个点。L将破坏所有的线路。但是他想知道当他破坏前i条线路时该城市有多少个块组成。我们认为当两个点可以通过线路直接或间接相互到达时,这两点属于同一个块
-
#include<stdio.h> int a[10001]; int find(int x)//查找函数 { if(x!=a[x]) a[x]=find(a[x]); return a[x]; } int main() { int n,m,i,num[100001],u[100001],v[100001],x,y; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0;i<n;i++) //下标值和其对应值相等,即开始时各个点间都是孤立的 a[i]=i; for(i=0;i<m;i++) //输入连通的点 scanf("%d%d",&u[i],&v[i]); num[m]=n; //当所有的点都没连通时,所需的通路最多 for(i=m-1;i>=0;i--)//反向思维 { x=find(u[i]); y=find(v[i]); if(x!=y)//当数组的值和下标值不相等时,说明多了一条通路 { a[x]=y; num[i]=num[i+1]-1; } else { num[i]=num[i+1]; } } for(i=1;i<=m;i++) printf("%d\n",num[i]); } }
-
这道题是并查集的一点点变形,我这里应用的是反向的思维,当所有的点都是孤立的时候,所需的连通路是最多的,就是本身的点数,然后从他要破坏的最后一条路算起,比较要破坏的通路的两端,如果经过查找后数组的值和下标值相等,说明连通数和破坏前的一样,(破坏两点的连通和生成两点之间的连通互逆,破坏到最后就是所有的点都没有连通,生成两点的连通起始情况就是所有点都不连通),感觉语言表达能力还是有待加强啊。。。有点表达不清。