思路:首先,如果按照正着走某一条桥拆了的话,其对应着的是反着走某一条桥被新建了。所以可以把题目想象成一开始都没有桥连通。先把每条桥能使用的时间从大到小排序(因为最后拆的桥对应逆向思维的第一条建的桥),然后用并查集判断一下接下来要建桥的两个点是否已经连通。若之前没有连通,建桥后连通,说明这是关键的一条桥,学生会起义。
#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;
}