luoguP1525关押罪犯

来源:互联网 发布:淘宝销量多久更新一次 编辑:程序博客网 时间:2024/06/03 19:16

解决方案:

1.按照冲突从大到小排序

2.优先保证最大冲突不发生(对,所以是贪心)

3.开一个并查集,维护必须在同一个监狱中和必须不在同一个监狱中的罪犯

4.等等,两个并查集

5.所以要有2倍的人

6.x变成x和x+n

7.x-y+n:x和y必须不在一起

8.x-y:x和y必须在一起

9.开始处理

10.假设目前处理到x和y

11.若在之前的处理中x和y已经被判要在一起

12.输出即可,return 0

13.若没有,会发现之前的东西有用了

14.所有和x不在一起的必须和y在一起,所有和y不在一起的必须和x在一起

15.合并一下

16.提交,会发现第一个点错了

17.最后要输出0

18.提交,AC

奉上代码

#include<iostream>#include<algorithm> using namespace std;int n,m;int ans;int f[40001];struct edge{    int a;    int b;    int c;}h[100001];bool cmp(edge x,edge y){    return x.c>y.c;}int find(int x){    if(x==f[x])return x;    return find(f[x]);

}//找祖先,用于合并

void unite(int x,int y){    f[find(y)]=find(x);    return;

}//合并

int main(){    cin>>n>>m;    for(int i=1;i<=n;i++)f[i]=i;    for(int i=1;i<=m;i++)    {        cin>>h[i].a>>h[i].b>>h[i].c;    }    sort(h+1,h+m+1,cmp);    for(int i=n+1;i<=2*n;i++)f[i]=i;    for (int i=1;i<=m;i++)    {        int j=find(h[i].a);        int k=find(h[i].b);        if (j==k)        {            cout<<h[i].c;            return 0;        }        if (j==find(h[i].b+n)||k==find(h[i].a+n))continue;        unite(j,k+n);        unite(k,j+n);    }    cout<<0;    return 0;}//似乎很简单
原创粉丝点击