当前位置: 代码迷 >> 综合 >> goj 1462 思维+并查集
  详细解决方案

goj 1462 思维+并查集

热度:42   发布时间:2023-12-16 03:32:19.0

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

#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;
}