【题解】关押罪犯

基本思路还是挺简单的吧

大体来说就是按照从大到小的顺序,解决每对人之间的矛盾,直到有一对人之间的矛盾无法解决,那么这对矛盾就是最大矛盾

证明也很简单,如果说这对无法解决的矛盾(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");//成功解决所有矛盾
}

 

posted @ 2018-10-05 18:32  小橘A  阅读(150)  评论(0编辑  收藏  举报