国王的烦恼
题意:
C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛。两个小岛间可能存在多座桥连接。然而,由于海水冲刷,有一些大桥面临着不能使用的危险。
如果两个小岛间的所有大桥都不能使用,则这两座小岛就不能直接到达了。然而,只要这两座小岛的居民能通过其他的桥或者其他的小岛互相到达,他们就会安然无事。但是,如果前一天两个小岛之间还有方法可以到达,后一天却不能到达了,居民们就会一起抗议。
现在C国的国王已经知道了每座桥能使用的天数,超过这个天数就不能使用了。现在他想知道居民们会有多少天进行抗议。
分析:
看到这个题的时候第一念头并没有想到并查集,(可能我太菜啦),我的第一个想法是,找到相同长度的边,算一天,其他不同的边,依次判断边的两个顶点是否还可以到达,如果可以那么继续删除其他的边,直到不能到达,结果就加一。但是实现起来发现特别麻烦的dfs,时间复杂度也高
看了大佬的题解,总结如下,将边权按照从大到小排序,遍历,每次合并边的两个顶点,如果说已经被合并过,那么说明这个边已经被计算了,就不用算了,如果说和前面天数一样的话,那么就是相当于这一天可以发生多次抗议,但是算一天,所以也不用计算了。
代码实现:
#include <iostream> #include <algorithm> using namespace std; const int N = 1e4+10; const int M = 1e5+10; struct edge{ int a,b; int val; bool operator < (const edge& a) const{ return this->val>a.val; } }; int fa[N]; int find(int a){ if(a==fa[a])return a; return fa[a]=find(fa[a]); } edge edges[M]; void un(int a,int b){ int af=find(a); int bf=find(b); fa[af]=bf; } int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++)fa[i]=i; for(int i=0;i<m;i++){ cin>>edges[i].a; cin>>edges[i].b; cin>>edges[i].val; } sort(edges,edges+m); int lastv=-1; int ans=0; for(int i=0;i<m;i++){ int a=edges[i].a; int b=edges[i].b; int v=edges[i].val; int af=find(a); int bf=find(b); if(af!=bf){ un(a,b); } if(af!=bf&&lastv!=v){ ans++; lastv=v; } } cout<<ans<<endl; }
还是要多刷图论,数论。

浙公网安备 33010602011771号