447. 修路
时间限制 3000 ms
内存限制 65536 KB
题目描述
小弱的学校很喜欢修路,现在给你一张他学校的地图,地图上有n个点和m条双向边,每条边代表一条路,这条路有可能是畅通,也有可能正在修路。大家都知道修路使得交通很不方便。所有小弱很想学校快快的把路修好,使得他能够很轻松的到达主楼915去刷题。但考虑到学校的施工能力有限,小弱想让你帮他算出学校需要集中力量马上修好的最少路数,使得他能够从学校任意点出发,在不经过正在施工的路下到达主楼(编号为1)。
输入格式
有多组数据。
每组数据以n( 1<=n<=10000), m(1<=m<=200000)开头。接下来一行有m行数。每行有三个数,对应于u, v, s,分别为这条路的两端点(编号从1到n)和路况,s = 0代表畅通, s = 1 代表正在修路。输入保证图是连通图。
输出格式
对每组数据输出对应的最少路数。
输入样例
3 2
1 2 0
1 3 1
3 2
1 2 0
1 3 0
3 2
1 2 1
1 3 1
输出样例
1
0
2
<pre name="code" class="cpp">#include <iostream>//用并查集来做;想到并查集,是因为本体要求的是看整个连通图被分为几个部分(注意是连通图所以不用考虑那种没路的可能); #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn=10004; int fa[maxn]; int flag[maxn]; <span style="font-family: Arial, Helvetica, sans-serif;">void init(int n)</span> { for(int i=0;i<=n;i++) { fa[i]=i; //rank[i]=1; } } int find(int x) { if(fa[x]==x) return x; else return fa[x]=find(fa[x]); } void unite(int x,int y) { x=find(x); y=find(y); fa[x]=y; //if(rank[x]==rank[y]) rank[x]++; } int u,v,s; int main() { int n,m; while(scanf("%d%d",&n,&m)==2) { init(n); int ans=0; while (m--) { scanf("%d%d%d",&u,&v,&s); if(s==0) unite(u,v);//有路的归到一个集合去; } memset(flag,0,sizeof(flag)); for(int i=1;i<=n;i++) flag[find(i)]=1;//将并查集的代表元素的flag设为1; for(int i=1;i<=n;i++) if(flag[i]==1) ans++;//查看形成几个并查集; printf("%d\n",ans-1); } return 0; }