题目来源:
https://www.luogu.org/problemnew/show/P1273
题目描述:
题目描述
SS城现有两座监狱,一共关押着NN名罪犯,编号分别为1-N1−N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为cc 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为cc的冲突事件。
每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里。公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。
在详细考察了NN 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。
那么,应如何分配罪犯,才能使Z 市长看到的那个冲突事件的影响力最小?这个最小值是多少?
输入输出格式
输入格式:
每行中两个数之间用一个空格隔开。第一行为两个正整数N,MN,M,分别表示罪犯的数目以及存在仇恨的罪犯对数。接下来的MM行每行为三个正整数a_j,b_j,c_jaj,bj,cj,表示a_jaj 号和b_jbj号罪犯之间存在仇恨,其怨气值为c_jcj。数据保证1<aj≤bj≤N ,0 < cj≤ 1,000,000,0001<aj≤bj≤N,0<cj≤1,000,000,000,且每对罪犯组合只出现一次。
输出格式:
共11 行,为ZZ 市长看到的那个冲突事件的影响力。如果本年内监狱中未发生任何冲突事件,请输出00。
输入输出样例
输入样例#1: 复制
4 6 1 4 2534 2 3 3512 1 2 28351 1 3 6618 2 4 1805 3 4 12884
输出样例#1: 复制
3512
说明
【输入输出样例说明】罪犯之间的怨气值如下面左图所示,右图所示为罪犯的分配方法,市长看到的冲突事件影响力是35123512(由22 号和33 号罪犯引发)。其他任何分法都不会比这个分法更优。
【数据范围】
对于30\%30%的数据有N≤ 15N≤15。
对于70\%70%的数据有N≤ 2000,M≤ 50000N≤2000,M≤50000。
对于100\%100%的数据有N≤ 20000,M≤ 100000N≤20000,M≤100000。
解题思路:
这题可以用并查集做,也可以用二分图判定做,我是用二分图做,我们二分怒气值,保留怒气值大于等于判断值的边,有bfs判断是否是二分图就行。
代码:
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
vector<pair<int,int> >E[20005];
int ls[20005],dis[100005],n,m;
bool bfs(int x,int t)
{
queue<int>q;
q.push(t);
ls[t]=1;
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=0;i<E[now].size();i++)
{
int v=E[now][i].first;
if(!ls[v]){
if(E[now][i].second>x){
if(ls[now]==1){
ls[v]=2;
q.push(v);
}
else{
ls[v]=1;
q.push(v);
}
}
}
else{
if(E[now][i].second>x&&ls[v]==ls[now])return 0;
}
}
}
return 1;
}
bool check(int x)
{
memset(ls,0,sizeof(ls));
for(int i=1;i<=n;i++)
{
if(!ls[i]){
if(!bfs(x,i))return 0;
}
}
return 1;
}
int main()
{
memset(dis,0,sizeof(dis));
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
E[a].push_back(make_pair(b,c));
E[b].push_back(make_pair(a,c));
dis[i]=c;
}
sort(dis,dis+1+m);
int r=m,l=0,ans;
while(l<=r)
{
int mid=(l+r)/2;
if(check(dis[mid])){
ans=dis[mid];r=mid-1;
}
else l=mid+1;
}
cout<<ans<<endl;
return 0;
}