总结
都说这个题是扩展域并查集入门题,我也就尝试学了一下,毕竟自己笨,一开始就学难的,脑袋就转不过来了了。
题意
两个囚犯之间有怨气值,如果把他们分在一个监狱就会发生冲突,我们想办法把这些囚犯分到两个监狱,保证最大的冲突怨气值最小。
解析
fat[N<<1],这里我们会开辟两个域,第一个域表示x在监狱1,第二个域表示x在监狱2
我们不断的删除边,从大到小,每删一条就代表x和y一定不在一个监狱。如果x和y已经在同一个监狱了,哪肯定不用删除了,ans就等于这条边的权值。
并查集维护的每棵树。用数据画图的时候,就很明显看出,是一个二分图。每一个监狱连接的其他监狱,一定不在一个监狱。如果这个监狱结点<=n,相邻结点就一定>n。
然后把怨气值从大到小划分,一直划分到在同一个监狱为止
后记
当了我做了食物链那个题后,每个结点维护的存在的所有状态,x在监狱1的状态,x在监狱2的状态
新的关系与之前冲突就结束
不冲突就建立关系
const int N=2e4+5;
const int M=1e5+5;
int fat[N<<1];
struct node
{
int x,y,v;
void input(){cin>>x>>y>>v;}
bool operator<(const node &b)const{return v>b.v;}
}s[M];
int find(int x)
{
return fat[x]==x?x:fat[x]=find(fat[x]);
}
signed main()
{
IOS;
//file();
int n,m;
cin>>n>>m;
for(int i=1;i<=n*2;i++)
fat[i]=i;
for(int i=0;i<m;i++)
s[i].input();
sort(s,s+m);
int ans=0;
for(int i=0;i<m;i++)
{
int x=find(s[i].x);
int y=find(s[i].y);
if(x==y)
{
ans=s[i].v;
break;
}
fat[x]=find(s[i].y+n);
fat[y]=find(s[i].x+n);
}
cout<<ans<<endl;
return 0;
}