【NOIP2010】关押罪犯
一开始看错题了,然后怎么想都想不明白……
原题:
S 城现有两座监狱,一共关押着 N 名罪犯,编号分别为 1~N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为 c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并 造成影响力为 c 的冲突事件。
每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表, 然后上报到 S 城 Z 市长那里。公务繁忙的 Z市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。
在详细考察了 N 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。那 么,应如何分配罪犯,才能使 Z 市长看到的那个冲突事件的影响力最小?这个最小值是多少?
N ≤ 20000,M ≤ 100000。
用并查集做更简单,然而为了我校信仰,我选择二分+二分图
二分一个答案,如果某条边的长度>这个答案说明这个边连接的两个点有冲突,应该放到两边
最开始看成放两个人一个监狱,然后看题解懵逼半天想不明白二分图和两两匹配有啥关系= =
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 int read(){int z=0,mark=1; char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')mark=-1; ch=getchar();} 9 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 10 return z*mark; 11 } 12 struct ddd{int next,y,value;}e[210000];int LINK[21000],ltop=0; 13 inline void insert(int x,int y,int z){e[++ltop].next=LINK[x];LINK[x]=ltop;e[ltop].y=y;e[ltop].value=z;} 14 int n,m; 15 int maxx=0; 16 int color[21000]; 17 bool dfs(int x,int y,int z){ 18 if(color[x]!=-1 && color[x]==color[y]) 19 return false; 20 if(color[x]==!color[y]) return true;//因为!color[y]只能是0或1,所以这里不用判断color[x]!=-1 21 color[x]=!color[y]; 22 for(int i=LINK[x];i;i=e[i].next)if(e[i].value>z) 23 if(e[i].y!=y && !dfs(e[i].y,x,z)) return false;//e[i].y不能是y,防止e[i].y和y之间死循环 24 return true; 25 } 26 bool check(int x){ 27 memset(color,-1,sizeof(color)); 28 bool can=true; 29 color[0]=0; 30 for(int i=1;i<=n;i++)if(color[i]==-1) 31 if(!dfs(i,0,x)){ can=false; break;} 32 return can; 33 } 34 int fen(){ 35 int fleft=0,fright=maxx,mid; 36 while(fleft+1<fright){ 37 mid=(fleft+fright)>>1; 38 if(check(mid)) fright=mid; 39 else fleft=mid; 40 } 41 return (check(fleft)) ? fleft : fright; 42 } 43 int main(){//freopen("ddd.in","r",stdin); 44 cin>>n>>m; 45 int _left,_right,_value; 46 while(m --> 0){//趋向于 47 _left=read(),_right=read(),_value=read(); 48 insert(_left,_right,_value),insert(_right,_left,_value); 49 maxx=max(maxx,_value); 50 } 51 cout<<fen()<<endl; 52 return 0; 53 }