二分图的判定 noip2010(分宿舍)

分宿舍

分宿舍
文件名 输入文件 输出文件 时间限制 空间限制
love.cpp love.in love.out 1s 128MB
题目描述
A 校有着神奇的住宿制度,不分男女宿舍,所有 n 个学生被统一分到两栋宿舍
楼中。作为年轻人,学生之间心生爱慕之情是很正常。我们用爱慕值来表示两名学
生之间的爱慕程度,如果两名爱慕值为 c 的学生被安排在同一宿舍楼,他们或她们
便会在一起,并造成影响力为 c 的早恋事件。
每年年末,身为政教处主任的你会将所有早恋事件按照影响力从大到小排成一
个列表,然后上报给校长。公务繁忙的校长只会去看列表中第一个事件的影响力,
如果影响很大,他会考虑撤换政教处主任。
在详细考察了 n 个学生之间的爱慕关系后,你觉得压力很大。你要合理的将学
生们分到两栋宿舍,以求产生的早恋事件影响力都比较小,以保住自己的官职。假
设只要处于同一栋宿舍楼的两个人之间有爱慕关系,他们就一定会在这年的某个时
候在一起。
那么,要怎么分配,才能让校长看到的那个早恋事件的影响力最小呢?这个最
小值是多少?
输入格式
第一行两个整数 n 和 m,分别表示学生的数目和爱慕关系的对数。
接下来 m 行,每行为 3 个正整数 ai,bi,ci,表示学生 ai 和 bi 之间有爱慕关
系,爱慕值为 ci。
数据保证 1 ≤ ai ≤ bi ≤ n,0 < ci ≤ 109,且每对爱慕关系只出现一次。
输出格式
输出一个数,为通过合理安排,校长看到的那个早恋事件的最小影响力。如果
没有发生早恋事件,输出 0。
6
样例输入
4 6
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884
样例输出
3512
数据范围
对于 30% 的数据,n ≤ 15。
对于 70% 的数据,n ≤ 2000,m ≤ 50000。
对于 100% 的数据,n ≤ 20000,m ≤ 100000。

二分图匹配+二分,标准的二分匹配代码:

void dfs(int x,int color)
   for(int i=0;i<g[x].size();i++){
		if(!v[g[x][i]]){
			dfs(g[x][i],3-color);
		} 
		else if(v[g[x][i]]==3-color) continue;
		else {
		//不是二分图
		}

这一题注意对于每一个点都要染色,因为可能这个图不连通。

#include<bits/stdc++.h>
using namespace std;
const int N=20005,M=1e5+7;
int n,m,v[M];
bool ok;
vector<pair<int,int> >g[N];
void dfs(int x,int color,int t){
//   cout << x << ' ' << color << endl;
    if(ok==0) return ;
    v[x]=color;
    for(int i=0;i<g[x].size();i++){
            if(g[x][i].second<=t) continue;
            if(v[g[x][i].first]==0){
                dfs(g[x][i].first,3-color,t);
            }
            else if(v[g[x][i].first]==3-color) continue;
            else{
                ok=0;
                return;
            };
        }
    }
bool check(int t){
    ok=1;
    memset(v,0,sizeof v);
    for(int i = 1; i <= n; i++) if(!v[i])
        dfs(i,1,t);
	if(ok) return true;
	return false;
}
int main(){
	freopen("love.in","r",stdin);//freopen("love.out","w",stdout);
	scanf("%d%d",&n,&m);
	int mx=0;
	for(int i=1,a,b,c;i<=m;i++) {
        scanf("%d%d%d",&a,&b,&c);
        g[a].push_back(make_pair(b,c));
        g[b].push_back(make_pair(a,c));
        mx=max(mx,c);
	}
	int l=0,r=mx,ans;
//	for(int i = 1; i <= m; i++) cout << s[i].a << ' ' << s[i].b << ' ' << s[i].c << endl;
//	for(int i = 1; i <= m; i++) if(s[i].c == 26123) cout << check(i) << endl;
	while(l<r){
		int mid=(l+r)>>1;
		if(check(mid))	{
            ans=mid,r=mid;
           // printf("%d\n",ans);
		}
		else l=mid+1;
	//	cout << l << ' ' << mid << ' ' << r << endl;
	}
	printf("%d\n",ans);
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值