题目
题解1
贪心+扩展域并查集
把怨气值排序,大的当然要分配到两个不同的监狱。
一个点拆成两个点,分两层,不同监狱连不同层。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=20010,maxm=100010;
int n,m;
int fa[maxn*2];
struct U{int x,y,c;}a[maxm];
bool cmp(U u1,U u2)
{
return u1.c>u2.c;
}
int find_fa(int x)
{
if(x==fa[x]) return x;
return find_fa(fa[x]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n*2;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].c);
}
sort(a+1,a+m+1,cmp);
for(int i=1;i<=m;i++)
{
fa[find_fa(a[i].x)]=find_fa(a[i].y+n);
fa[find_fa(a[i].x+n)]=find_fa(a[i].y);
if(find_fa(a[i].x)==find_fa(a[i].y))
{
printf("%d\n",a[i].c);
return 0;
}
}
printf("0\n");
return 0;
}
题解2
二分+黑白染色
答案显然满足二分性,问题转变成判断是否存在一种分配方案,使得所有大于mid的怨气值的人被分在不同监狱。
删掉所有边权小于等于mid的边,然后做黑白染色。如果染色中不发生冲突,那么这个mid可行。
黑白染色就好像在说,与我连边(怨气值大于mid)的人都不能和我有一样的颜色(监狱)。
这是利用了黑白染色可以判断是否是二分图的特点。其原理是判断是否有奇环,如果一张图有一个奇环,那么所有的点都存在与某个奇环。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=20010,maxm=100010;
int n,m;
struct E{int y,c,next;}e[maxm<<1];int len=0,last[maxn];
void ins(int x,int y,int c)
{
e[++len]=(E){y,c,last[x]};last[x]=len;
}
int c[maxn];
bool dfs(int x,int color,int mid)
{
c[x]=color;
for(int k=last[x];k;k=e[k].next)
{
int y=e[k].y;
if(e[k].c<=mid) continue;
if(c[y] && c[y]==color) return false;
else if(!c[y])
if(!dfs(y,3-color,mid)) return false;
}
return true;
}
bool check(int mid)
{
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)//debug 枚举所有
if(c[i]==0)
if(!dfs(i,1,mid)) return false;
return true;
}
int main()
{
int mxc=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
ins(x,y,c);ins(y,x,c);
mxc=max(mxc,c);
}
int l=0,r=mxc,ans;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d",ans);
return 0;
}