1. 程式人生 > >luogu1525關押罪犯

luogu1525關押罪犯

AC 說明 bsp cout span map 題解 發生 同學

#這題用並查集!!

剛一開始看的時候懵了,這題怎麽做,後來看了一下別人的題解,別人也沒怎麽說明白,最後自己根據別人的代碼手動模擬了一下。跟你們說下我的理解與感悟。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define X 100000+7
using namespace std;
int fa[X];//父親
struct Node{
    int u,v,w;
}map[X];//罪犯之間的關系
bool pd(Node a,Node b)
{
    
return a.w>b.w; }//重新定義sort的排序,由大到小排序 int find(int x) { if(fa[x]==x)return x; return fa[x]=find(fa[x]); }//查找父親節點 int hb(int x,int y) { int ff=find(x),fff=find(y); fa[ff]=fff; }//並查集的合並 int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=2*n;++i)//這裏是一個難點,有的同學就要問了,為什麽i要在1和2*n之間定義呢,我們是把n+1~2*n定義為1~n罪犯的敵人(互相看不服的罪犯)為什麽要用2*n呢,因為n是不確定的,要找到他的敵人,就要開2倍的數組
{ fa[i]
=i; } for(int i=1;i<=m;++i) { scanf("%d%d%d",&map[i].u,&map[i].v,&map[i].w); } sort(map+1,map+m+1,pd);//這裏由大到小排序,運用了貪心思想。因為要保證看到的最小,所以要保證倆個火氣大的罪犯分開
 
for(int i=1;i<=m;++i) { int ff=find(map[i].u),fff=find(map[i].v); if(ff==fff)//如果倆互相看不服對方的罪犯在同一監獄,就輸出他們之間的火氣值,因為火氣值是從大到小排序的,之後就算有互相看不服的罪犯在同一監獄,也比此時的火氣值小
{ cout
<<map[i].w; return 0; } hb(map[i].u,map[i].v+n);//這時要讓互相看不服對方的X,Y。X要與Y之後看不服的罪犯合住一監獄 hb(map[i].v,map[i].u+n);//同上 } cout<<0;//若最後沒有發生火氣值,直接輸出就好了 }

luogu1525關押罪犯