思路:首先,如果按照正着走某一条桥拆了的话,其对应着的是反着走某一条桥被新建了。所以可以把题目想象成一开始都没有桥连通。先把每条桥能使用的时间从大到小排序(因为最后拆的桥对应逆向思维的第一条建的桥),然后用并查集判断一下接下来要建桥的两个点是否已经连通。若之前没有连通,建桥后连通,说明这是关键的一条桥,学生会起义。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node
{
int x,y,d;
} s[10005];
int n,f[10005];
bool cmp(node a,node b) //按天数的大小从大到小来排序
{
return a.d>b.d;
}
void Set()
{
for (int i=1; i<=n; i++)
f[i]=i;
}
int Find(int x) //查找根节点
{
if (f[x]==x)
return x;
return f[x]=Find(f[x]);
}
bool Union(int x,int y)
{
x=Find(x);
y=Find(y);
if (x!=y)
{
f[x]=y;
return 1;
}
return 0;
}
int main()
{
int m;
while (~scanf("%d%d",&n,&m))
{
for (int i=1; i<=m; i++)
{
scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].d);
}
sort(s+1,s+m+1,cmp);
Set();
int pre=-1,ans=0; //表示前一次是在第几天进行反抗的
for (int i=1; i<=m; i++)
{
int way=Union(s[i].x,s[i].y); //并查集反向建桥,way=0表示之前有桥,不需要在建桥
if (way==1&&s[i].d!=pre) //如果之前没桥,而且天数不相等的话,居民就抗议一次
{
ans++;
pre=s[i].d;
}
}
cout<<ans<<endl;
}
return 0;
}