noip2010 关押罪犯 二分答案+二分图判断
2016-10-07 13:14
288 查看
之前写过一个用虚点并查集做的,今天终于用二分ac了。
大体思路:
二分答案,小于mid的边忽略不计,如果不能构成二分图就要往大找让l=mid,如果可以就r=mid。
判断二分图要注意每次初始化color,可以用0和1也可以用1和2表示。从1到n循环,如果没有标记的就开始深搜,每次深搜把所有邻边染色。
其实还是参考了很多别人的代码...
一开始搞不明白标记的问题,后来终于想通,求最小值,如果ok的话要往下找,也就是r=mid,之前一直没转过弯来。
不知道为什么好多人每次二分都要重新构图,直接判断一下不就可以了吗?
http://blog.csdn.net/moon_sky1999/article/details/52744564?locationNum=2
这一篇还很好理解,只不过一层一层地往下堆代码有点吓人,在这个的基础上改了个dfs,下面贴代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=2e4+1;
const int inf=1e9;
int mid;
bool ok;
struct node{int t,w;};
vector<node> a[maxn];
int color[maxn]={0};
bool inq[maxn]={0};
void dfs(int x)
{
if(ok==0)
return;
for(int j=0;j<a[x].size();j++)
{
int w=a[x][j].w;
int t=a[x][j].t;
if(w<=mid) continue;
if(color[t]==0)
{
color[t]=3-color[x];
dfs(t);
}
else if(color[t]==color[x])
{
ok=0;
return;
}
}
}
int main()
{
ios::sync_with_stdio(false);
int n,m;cin>>n>>m;
int r=-inf,l=inf;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
node e;e.w=z;
e.t=y;a[x].push_back(e);
e.t=x;a[y].push_back(e);
l=min(z,l);
r=max(r,z);
}
if(l==r)l=0;
while(l<r)
{
mid=(l+r)/2;
memset(color,0,sizeof(color));
memset(inq,0,sizeof(inq));
ok=1;
for(int i=1;i<=n;i++)
{
if(color[i]==0)
{
color[i]=1;
dfs(i);
}
if(ok==0)
break;
}
if(ok)r=mid;
else l=mid+1;
}
cout<<l;
return 0;
}
大体思路:
二分答案,小于mid的边忽略不计,如果不能构成二分图就要往大找让l=mid,如果可以就r=mid。
判断二分图要注意每次初始化color,可以用0和1也可以用1和2表示。从1到n循环,如果没有标记的就开始深搜,每次深搜把所有邻边染色。
其实还是参考了很多别人的代码...
一开始搞不明白标记的问题,后来终于想通,求最小值,如果ok的话要往下找,也就是r=mid,之前一直没转过弯来。
不知道为什么好多人每次二分都要重新构图,直接判断一下不就可以了吗?
http://blog.csdn.net/moon_sky1999/article/details/52744564?locationNum=2
这一篇还很好理解,只不过一层一层地往下堆代码有点吓人,在这个的基础上改了个dfs,下面贴代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=2e4+1;
const int inf=1e9;
int mid;
bool ok;
struct node{int t,w;};
vector<node> a[maxn];
int color[maxn]={0};
bool inq[maxn]={0};
void dfs(int x)
{
if(ok==0)
return;
for(int j=0;j<a[x].size();j++)
{
int w=a[x][j].w;
int t=a[x][j].t;
if(w<=mid) continue;
if(color[t]==0)
{
color[t]=3-color[x];
dfs(t);
}
else if(color[t]==color[x])
{
ok=0;
return;
}
}
}
int main()
{
ios::sync_with_stdio(false);
int n,m;cin>>n>>m;
int r=-inf,l=inf;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
node e;e.w=z;
e.t=y;a[x].push_back(e);
e.t=x;a[y].push_back(e);
l=min(z,l);
r=max(r,z);
}
if(l==r)l=0;
while(l<r)
{
mid=(l+r)/2;
memset(color,0,sizeof(color));
memset(inq,0,sizeof(inq));
ok=1;
for(int i=1;i<=n;i++)
{
if(color[i]==0)
{
color[i]=1;
dfs(i);
}
if(ok==0)
break;
}
if(ok)r=mid;
else l=mid+1;
}
cout<<l;
return 0;
}
相关文章推荐
- NOIP 2010 - 提高组 关押罪犯 二分答案+二分图的判定
- NOIP 2010 关押罪犯 二分答案+二分图染色判定 COGS 520
- NOIP2010 关押罪犯 (二分答案+二分图染色)
- NOIP 2010 关押罪犯 并查集 二分+二分图染色
- NOIP2010关押罪犯[并查集|二分答案+二分图染色 | 种类并查集]
- codevs 1069 [NOIP2010] 关押罪犯 二分+二分图染色
- [NOIP2010]关押罪犯(二分+二分图染色)
- [NOIP2010]关押罪犯(二分+二分图染色)
- [NOIP2010][并查集][二分答案]关押罪犯
- NOIP 2010 关押罪犯 并查集 二分+二分图染色
- 【图-二分图染色】NOIP2010提高组关押罪犯
- noip 2010 关押罪犯 (二分图染色 并茶几)
- 【NOIP2010】关押罪犯 (二分+图染色)||(贪心+并查集)
- NOIP2010 Codevs 1069 关押罪犯 [并查集] [二分图判定]
- NOIP2010 关押罪犯 解题报告(并查集,补集判断思想)
- NOIP2010 关押罪犯(图论+二分)
- 【noip2010】codevs 1069 关押罪犯(二分+BFS染色||并查集)
- noip2010 关押罪犯 (并查集处理二分图分配)
- 【二分+染色】【NOIP2010】关押罪犯 prison
- 关押罪犯-详解-noip2010-并查集--搜索--二分图