传送门(洛谷)
贪心+并查集维护
先进性排序,将怨气值最大的一对拆开,分别找出每一个人的“死敌”,然后和自己的“死敌”分离开(用并查集维护就可以),最后只需要找出第一个两个人必须在一个监狱的情况(也就是在同一个并查集中),就是最后的答案。
举个例子:
先贪心按照权值大小进行排序,在枚举到两个人
u
,
v
u,v
u,v时
u
,
v
u,v
u,v对应的死敌分别是
u
′
,
v
′
u',v'
u′,v′。则
u
,
v
′
u,v'
u,v′一定在一个集合,
u
′
,
v
u',v
u′,v一定在一个集合。然后就找到一对
u
,
v
u,v
u,v在同一个集合就可以了
Code
#include<bits/stdc++.h>
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define ll long long
using namespace std;
const int maxn=1e6+10;
const int maxm=2500+10;
int n,m;
int fa[maxn],vis[maxn];
template <class t> inline void read(t &x) {
int f=1;x=0;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') ch=getchar();ch=getchar();}
while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
x*=f;
}
struct node{
int u,v,w;
bool friend operator < (const node &A,const node &B) {
return A.w>B.w;
}
}e[maxn<<1];
inline int find(int x) {
if(x==fa[x]) return x;
else return fa[x]=find(fa[x]);
}
void meger(int x,int y) {
int fx=find(x),fy=find(y);
fa[fx]=fy;
}
void readdata() {
read(n),read(m);
rep(i,1,m) {
read(e[i].u);
read(e[i].v);
read(e[i].w);
}
sort(e+1,e+1+m);
}
bool check(int x,int y) {
int fx=find(x),fy=find(y);
if(fx==fy) return true;
return false;
}
void work() {
rep(i,1,n) fa[i]=i;
rep(i,1,m) {
if(check(e[i].u,e[i].v)) {printf("%d\n",e[i].w);exit(0);}
else {
if(!vis[e[i].u]) vis[e[i].u]=e[i].v;
else meger(vis[e[i].u],e[i].v);
if(!vis[e[i].v]) vis[e[i].v]=e[i].u;
else meger(vis[e[i].v],e[i].u);
}
}
printf("0\n");
}
int main() {
//freopen("police.in","r",stdin);
readdata();
work();
return 0;
}