A. 修路 2014新生暑假个人排位赛06
时间限制 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
思路:这道题没有给出权值,直接就要求你求出最少加的。那最少加的就是每一次先把同一个联通块的并在一起,然后若有新的联通块就加进去就肯定是最短的。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#define maxn 20000
#define maxm 500000
//#define LOCAL
using namespace std;
int n,m,x,y,v,cnt,num,ans;
int father[maxn];
int from[maxm],to[maxm];
int getfather(int x)
{
if(father[x]==x)return x;
return father[x]=getfather(father[x]);
}
void Union(int x,int y,int v)
{
int f1=getfather(x);
int f2=getfather(y);
if(f1!=f2){num++;if(v==1)ans++;father[f2]=f1;}
}
int main()
{
#ifdef LOCAL
freopen("input.txt","r",stdin);
#endif // LOCAL
while(scanf("%d%d",&n,&m)==2)
{
cnt=0;num=1;ans=0;
//memset(h,-1,sizeof(h));
for(int i=1;i<=n;i++)father[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&v);
if(v==0)Union(x,y,0);
else{cnt++;from[cnt]=x;to[cnt]=y;}
}
if(cnt==0){printf("0\n");continue;}
for(int i=1;i<=cnt;i++)
{
Union(from[i],to[i],1);
if(num==n)break;
}
printf("%d\n",ans);
}
return 0;
}