Solution 1:擴展域並查集
QAQ之前做過並的查集做法。
按權值排序,優先把大權值的分開
對於一個節點a,a+n表示和它不在一個監獄裏
代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn1=20000+50,maxn2=100000+50;
int n,m,ans=0;
int fa[maxn1*2];
int cnt[maxn1*2];
struct hh
{
int a,b,c;
}e[maxn2];
bool cmp(hh x,hh y)
{
return x.c>y.c;
}
int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
int main()
{
memset(fa,0,sizeof(fa));
scanf("%d%d",&n,&m);
int N=n*2;
for(int i=1;i<=N;++i)
fa[i]=i;
for(int i=1;i<=m;++i)
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
sort(e+1,e+m+1,cmp);
int k=0;
for(int i=1;i<=m;++i)
{
int f1=find(e[i].a);
int f2=find(e[i].b);
if(f1!=f2)
{
fa[f1]=find(e[i].b + n);
fa[f2]=find(e[i].a + n);
}
if(f1==f2 && k==0)
{
ans=e[i].c;
k=1;
}
}
printf("%d",ans);
return 0;
}
Solution 2:二分答案+二分圖染色
這個也不難。
二分答案,只要權值大於這個答案的,都染爲不同的顏色,看是否能夠完成染色。這裏注意權值小於答案的,我們暫時不作處理(QAQ一開始因爲這個wa了),因爲它無論是分開還是不分開,都對答案沒有影響,所以順其自然染色,如果強行染色,會對後面的染色產生影響
代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=20000+10;
int n,cnt,ans,m,tot;
int fist[maxn],nxt[maxn*10],c[maxn*5],color[maxn];
bool vis[maxn];
struct hh
{
int f,t,v;
}e[maxn*10];
queue<int>q;
void build(int f,int t,int v)
{
e[++cnt]=(hh){f,t,v};
nxt[cnt]=fist[f];
fist[f]=cnt;
}
bool done(int ds,int x)
{
q.push(ds);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=fist[u];i!=-1;i=nxt[i])
{
int v=e[i].t;
if(e[i].v>x)
{
if(!vis[v])
{
color[v]=color[u]^1;
vis[v]=true;
q.push(v);
cnt++;
}
else if(color[v]==color[u]) return false;
}
}
}
return true;
}
bool check(int x)
{
while(!q.empty()) q.pop();
memset(vis,0,sizeof(vis));
memset(color,0,sizeof(color));
tot=0;
for(int i=1;i<=n;++i)
{
if(!vis[i])
{
color[i]=1;
vis[i]=true;
tot++;
if(!done(i,x)) return false;
}
if(tot==n) break;
}
return true;
}
int main()
{
memset(fist,-1,sizeof(fist));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
{
int a,b;
scanf("%d%d%d",&a,&b,&c[i]);
build(a,b,c[i]);
build(b,a,c[i]);
}
sort(c+1,c+m+1);
int l=0,r=m+1;
while(l+1<r)
{
int mid=(l+r)>>1;
if(check(c[mid])) r=mid;
else l=mid;
}
if(check(c[l])) ans=c[l];
else ans=c[r];
printf("%d",ans);
return 0;
}