问题描述:
输入输出样例:
思路:
首先我们对桥进行排序(根据桥的时间排序,时间长的放在前面),然后遍历每一座桥,若桥刚好连接了两个不为同一祖先的两座城市,而且该桥的时间与我们每次更新的时间不一样时,(若存在两座桥的时间相同且刚好连接了跟上述说法中一样的两座城市,没有这一判断条件我们便会得到错误答案。)我们对答案加一,并且在此更新我们维护的时间。这也是为什么在开始阶段我们要根据每一座桥的时间来对桥进行排序的原因。
注意事项:
1.我们在判断两座城市是否是刚联通时(即判断的这座桥连接了这两座城市),我们应该更新我们的并查集。
2.我们一定要加上时间并且维护更新时间。
3.首先要初始化我们的并查集和时间,将桥根据时间进行排序。
AC代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N=10010;
const int M=100010;
struct Bridge//定义一个结构体表示桥
{
int x,y;//x,y分别表示桥相连的两个小岛
int day;//day表示桥的使用天数
Bridge(){};
Bridge(int a,int b,int c):x(a),y(b),day(c){};
};
int pre[N];//用于存储每个小岛的"上一级"
Bridge bridge[M];//用于存储所有的桥
void init(int n)//初始化每个小岛,让其上一级为其本身
{
for(int i=1;i<=n;i++)
{
pre[i]=i;
}
}
int find_pre(int n)//找到某个小岛的祖先
{
if(pre[n]==n)
return n;
else return pre[n]=find_pre(pre[n]);
}
bool Union(int x,int y)//连通两个小岛,如果两个小岛不连通则返回真,连通返回假
{
int rootx=find_pre(x);
int rooty=find_pre(y);
if(rootx!=rooty)
{
pre[rootx]=rooty;
return true;
}
else
return false;
}
bool cmp(Bridge a,Bridge b)
{
return a.day>b.day;
}
int main()
{
int n,m,a,b,t;
cin>>n>>m;
init(n);//初始化每个小岛
for(int i=1;i<=m;i++)
{
cin>>a>>b>>t;
bridge[i]=Bridge(a,b,t);
}
sort(bridge+1,bridge+1+m,cmp);
int ans=0,lastday=0;//ans表示抗议次数,lastday表示一次某个桥的使用天数
for(int i=1;i<=m;i++)
{
bool flag=Union(bridge[i].x,bridge[i].y);//如果为真表示当前两个小岛为连通
if(flag&&bridge[i].day!=lastday)//未连通,且此桥的天数第一次出现,那么就增加了抗议天数
{
ans++;
lastday=bridge[i].day;
}
}
cout<<ans<<endl;
return 0;
}