【题解】关押罪犯
基本思路还是挺简单的吧
大体来说就是按照从大到小的顺序,解决每对人之间的矛盾,直到有一对人之间的矛盾无法解决,那么这对矛盾就是最大矛盾
证明也很简单,如果说这对无法解决的矛盾(A)和之前已经解决了的矛盾(B)交换一下,那么虽然A解决了,但是B没有解决,又因为我们是按照从大到小的顺序解决的所以B一定不小于A,因此最大矛盾值将增大,因此不交换的解更优
还有一点就是如何判断矛盾能否解决,这里作者太弱了,于是就用矛盾可以解决就加边的方式,如果2个点深度之和为偶数,那么矛盾就不可避免(这个比较好想),所以每次dfs就可以了
最后上代码
#include<iostream> #include<cstdio> #include<queue> using namespace std; priority_queue<pair<int,int> >build;//用于排序,pair还是挺好用的,不会的话可以百度一下 int z[100002],x[100002],y[100002],deep[20002],vis[20002],head[20002]; int n,m,num; struct hat { int to; int next; int we; }hate[200002]; void add(int fr,int to,int we) { hate[++num].to=to; hate[num].we=we; hate[num].next=head[fr]; head[fr]=num; }//邻接链表储存 void dfs(int a,int dep) { deep[a]=dep; vis[a]=1; for(int i=head[a];i!=0;i=hate[i].next) { if(!vis[hate[i].to])dfs(hate[i].to,dep+1); } } int main() { scanf("%d %d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d %d %d",&x[i],&y[i],&z[i]); build.push(make_pair(z[i],i)); } int flag=1; while(flag&&!build.empty()) { int se=build.top().second; build.pop(); for(int i=1;i<=n;i++)vis[i]=0; dfs(x[se],1); if(vis[y[se]]) {//矛盾不可调和部分 if((deep[x[se]]+deep[y[se]])%2==0) { flag=0; printf("%d",z[se]); } } add(x[se],y[se],z[se]); add(y[se],x[se],z[se]); } if(flag==1)printf("0");//成功解决所有矛盾 }