您的位置:首页 > 其它

noip 2010 关押罪犯 (二分图染色 并茶几)

2016-05-31 21:48 417 查看


/*
二分图染色版本
两个监狱对应二部图的两部分
在给定的怨气值里二分
对于每一个Ci进行染色判断是否合法
染色的时候如果这条边的ci>Ci这两个人就带分开即染成不同的颜色
如果染色到某两个点颜色相同且怨气值>Ci这个Ci就不合法
二分直到最后答案
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#definemaxn100010
usingnamespacestd;
intn,m,num,head[maxn],Ci,ans,color[maxn];
structnode
{
intv,t,pre;
}e[maxn*2];
structnope
{
intx,y,z;
}p[maxn];
intcmp(constnope&a,constnope&b)
{
returna.z<b.z;
}
voidAdd(intfrom,intto,intdis)
{
num++;
e[num].t=dis;
e[num].v=to;
e[num].pre=head[from];
head[from]=num;
}
boolColor(ints)
{
for(inti=head[s];i;i=e[i].pre)
if(e[i].t>Ci)
{
if(color[s]==color[e[i].v])return0;
if(color[e[i].v]==0)
{
color[e[i].v]=3-color[s];
if(!Color(e[i].v))return0;
}
}
return1;
}
boolpd()
{
for(inti=1;i<=n;i++)
if(color[i]==0)
{
color[i]=1;
if(!Color(i))return0;
}
return1;
}
intmain()
{
scanf("%d%d",&n,&m);
intu,v,t;
for(inti=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&t);
p[i].x=u;p[i].y=v;p[i].z=t;
Add(u,v,t);Add(v,u,t);
}
sort(p+1,p+1+m,cmp);
intl=0,r=m;
while(l<=r)
{
memset(color,0,sizeof(color));
intmid=(l+r)/2;
Ci=p[mid].z;
if(pd())
{
r=mid-1;
ans=Ci;
}
elsel=mid+1;
}
printf("%d\n",ans);
return0;
}






/*
并茶几版本
因为就有两个监狱两个人要么一个监狱要么不一个监狱(废话--)
为了使ans最小我们一定会让ci大的组合先分开
所以按ci排一遍序然后for每一对
如果发现他俩在一个集合输出ci结束
否则的话我们希望的是把他两个分开
即把他们分别跟对方的仇人合并
所以我们假设每个人的仇人都是i+n
对于i如果另外两个人都合并到了i+n说明两个人一定在一所监狱
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#definemaxx40010
#definemaxn200010
usingnamespacestd;
intfa[maxx],n,m;
structnode
{
inta;
intb;
intc;
}s[maxn];
intcmp(constnode&x,constnode&y)
{
returnx.c>y.c;
}
intfind(intx)
{
if(x!=fa[x])fa[x]=find(fa[x]);
returnfa[x];
}
intmain()
{
inti,j;
cin>>n>>m;
for(i=1;i<=n*2;i++)fa[i]=i;
for(i=1;i<=m;i++)
cin>>s[i].a>>s[i].b>>s[i].c;
sort(s+1,s+1+m,cmp);
for(i=1;i<=m;i++)
{
intr1=find(s[i].a);
intr2=find(s[i].b);
if(r1==r2)
{
cout<<s[i].c;
return0;
}
fa[r1]=find(s[i].b+n);
fa[r2]=find(s[i].a+n);
}
cout<<0;
return0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: