Bipartite graph matching

subject

Blog Park Address
Title Description
There are two prisons in S City, holding a total of NN criminals, numbered 1-N1 − N. Naturally, the relationship between them is also extremely disharmonious. Many criminals have even accumulated grievances for a long time. If objective conditions are met, conflicts may break out at any time. We use "resentment value" (a positive integer value) to express the degree of hatred between two criminals. The greater the resentment value, the more resentment between the two criminals. If two criminals with grievance value of cc are detained in the same prison, there will be friction between them and lead to conflict with influence of cc.

At the end of each year, the police station will make a list of all conflicts in the prison this year, from large to small, and then report it to mayor Z of S city. Busy mayor Z will only look at the influence of the first event on the list. If the influence is very bad, he will consider replacing the police chief.

After a detailed investigation of the contradictory relationship between NN criminals, the police chief felt great pressure. He plans to redistribute the criminals in the two prisons in order to have less influence on the conflict, so as to keep his black hat. Suppose that as long as there is hatred between two criminals in the same prison, they will have friction at some time of the year.

So, how should criminals be allocated to minimize the impact of the conflict seen by Mayor Z? What is the minimum value?

Input format
Two numbers in each line are separated by a space. The first line is two positive integers n, Mn and m, which respectively represent the number of criminals and the logarithm of criminals with hatred. The next MM line each line has three positive integers a_j,b_j,c_jaj, bj, cj, denotes a_jaj # and B_ There is hatred between criminals jbj # and their resentment value is c_jcj​. Data assurance 1 < A_ j\leq b_ j\leq N, 0 < c_ J \ Leq 10 ^ 91 < AJ ≤ bj ≤ n, 0 < cj ≤ 109, and each pair of criminals only appears once.

Output format
A total of 11 lines show the influence of the conflict seen by Mayor Z. If there is no conflict in the prison this year, please output 0.

Input and output samples
Enter #1 copy
4 6
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884
Output #1 copy
3512
Description / tips
[description of input and output examples] the grievance value between criminals is shown in the left figure below, the right figure shows the distribution method of criminals, and the influence of conflict events seen by the mayor is 35123512 (caused by criminals 22 and 33). No other method is better than this one.

[data range]

For 30% 30% data, N\leq 15N ≤ 15.

For 70% and 70% of the data, N\leq 2000,M\leq 50000N ≤ 2000,M ≤ 50000.

For 100% 100% data, there are n \ Leq 20000,M \ Leq 100000, n ≤ 20000,M ≤ 100000.

Incomplete understanding of this konjaku (I hope you can give me some advice):

Bipartite answer + bipartite graph judgment (coloring method)

Because there are two sets, and considering finding the minimum value of the maximum anger value, sort the edges according to the weight from small to large, judge the mid through the dichotomous answer (subscript), and connect the edges after the mid (because it is sorted from small to large, separate the grievance value from large to small (that is, separate the grievance value as much as possible) Finally, judge whether it can form a bipartite graph. If so, it means that the people before mid can be divided into two groups, so as to separate the people with grievance value, then r=mid. if not, l=mid+1. Finally, find the grievance value corresponding to the smallest mid.

Query mid:

First, pay attention to clearing the previously created graph and initializing the color array (because there are multiple groups of mid values). Then, create the graph from mid+1. After that, judge the bipartite graph.

The code implementation is as follows:

 1 bool check(int pos)
 2 {
 3     for(int i=1;i<=n;i++)    e[i].clear();
 4     for(int i=pos+1;i<=m;i++)
 5     {
 6         e[a[i].x].push_back(a[i].y);
 7         e[a[i].y].push_back(a[i].x);
 8     }
 9     flag=true;
10     memset(color,0,sizeof(color));
11     for(int i=1;i<=n;i++)
12         if(!color[i])
13         {
14             dfs(i,1);
15             if(!flag)    return false;
16         }
17     return true;
18 }

Judgment of bipartite graph:

Enumerate each point. If the point is not stained, perform a deep search through the point (because there is no guarantee that there must be only one graph):

If w is dotted as c and all edges starting from w are enumerated, then all corresponding dotted as - c. If a contradiction is finally found, false is returned (flag is used here)

The code implementation is as follows:

#include<bits/stdc++.h>
using namespace std;
int n,m,color[20010];
vector<int>    e[20010];
bool flag;
struct an
{
    int x,y,z;
}a[100010];
bool comp(an e1,an e2)
{
    return e1.z<e2.z;
}
void dfs(int w,int c)
{
    color[w]=c;
    for(int i=0;i<e[w].size();i++)
    {
        int v=e[w][i];
        if(!color[v])
            dfs(v,-c);
        if(color[v]==c)
            flag=false;
    }
}
bool check(int pos)
{
    for(int i=1;i<=n;i++)    e[i].clear();
    for(int i=pos+1;i<=m;i++)
    {
        e[a[i].x].push_back(a[i].y);
        e[a[i].y].push_back(a[i].x);
    }
    flag=true;
    memset(color,0,sizeof(color));
    for(int i=1;i<=n;i++)
        if(!color[i])
        {
            dfs(i,1);
            if(!flag)    return false;
        }
    return true;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
    sort(a+1,a+m+1,comp);
    int l=0,r=m,mid;
    while(l<r)
    {
        mid=(l+r)/2;
        if(check(mid))
            r=mid;
        else
            l=mid+1;
    }
    if(m==1)    cout<<0<<endl;
    else    cout<<a[l].z<<endl;
    return 0;
}

Combined query set:

In addition to two points, what you can think of is to separate those with high resentment value as far as possible into two sets. In the end, if you find that there is no way, you will output anger value.

First sort the edges (from large to small), and then enumerate from the first one. When the two points of the edge are in the same set, it means that the anger value has been separated as much as possible through the previous connection, then the weight of the edge (i.e. the minimum value of the maximum anger value) is output On the contrary, find the ancestors of two points and judge two sets: if one has no enemy, separate the two (become an enemy); on the contrary, merge one person's enemy with another (the enemy of the enemy is a friend).

The code implementation is as follows:

#include<bits/stdc++.h>
using namespace std;
int n,m;
int f[20005],fight[20005];
struct an{
    int r,t,s;
}e[100005];
bool comp(an e1,an e2)
{
    return e1.s>e2.s;
}
int gf(int v)

{
    if(f[v]==v)    return v;
    f[v]=gf(f[v]);
    return f[v];
}
void add(int a,int b)
{
    a=gf(a);
    b=gf(b);
    if(a!=b)    f[a]=b;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)    f[i]=i;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&e[i].r,&e[i].t,&e[i].s);
    }
    sort(e+1,e+m+1,comp);
    for(int i=1;i<=m+1;i++)
    {
        int u=e[i].r,v=e[i].t;
        if(gf(u)==gf(v))
        {
            cout<<e[i].s<<endl;
            return 0;
        }
        else
        {
            u=gf(u);v=gf(v);
            if(!fight[u])
                fight[u]=v;
            else
                add(fight[u],v);

            if(!fight[v])
                fight[v]=u;
            else
                add(fight[v],u);
        }
    }
    return 0;
}

Thank you for coming to my blog!

Tags: Algorithm

Posted on Mon, 08 Nov 2021 17:38:59 -0500 by ipwnzphp