The 12 Graph Theory Training

bzOJ2654: tree

Description

You give a free communication to FIG weighted, each edge is black or white. Let you find a minimum weight of just good and need spanning tree white side stripe.
Topic guarantee solvable.
Input

The first line V, E, need denote points, the number of edges and the number of required white edges.
Next E lines of s, t, c, col represents a side end (reference point from 0), the right side, color (Black 0 White 1) .
Output

Row represents the right side asked for and spanning tree.
V <= 50000, E <= 100000, all data to the right side [1100] positive integers.
Sample Input

2 2 1
0 1 1 1
0 1 2 0
Sample Output

2

Review the wqs half

Ideas: WQS dichotomy
is obvious that this is a minimum spanning tree. .....
But the question is which on the black and white sides and white border size requirements.

According to kruskal practice, we found that the priority to choose sides very dependent on the right side ,

If we can put the right side of the white side will be expanded (shrink), then it can be done to control the number of white side up.

Then consider: When all the white side are offset after adding an offset, a minimum spanning tree can be determined,

Then the answer is subtracted tree ** All white side offset number * , in fact, this is a legitimate spanning tree.
offset is too large to select the
white side too , otherwise too much **.

We found that the number of white border with incremental offset is incremented, so we can dichotomous answers , two points offset the size of solving .

code:
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXE=100010;
struct edge
{
    int u,v,w,c;
}E[MAXE];
int v,e,need,wn,ans,tot;
int f[MAXE/2];
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
bool cmp(edge a,edge b){return a.w==b.w?a.c<b.c:a.w<b.w;}
int kruskal(int add)
{
    for(int i=1;i<=v;i++)f[i]=i;
    for(int i=1;i<=e;i++)
        if(!E[i].c)E[i].w+=add;
    sort(E+1,E+1+e,cmp);
    int cnt=0,w=0;tot=0;
    for(int i=1;i<=e;i++)
    {
        if(find(E[i].u)!=find(E[i].v))
        {
            f[find(E[i].u)]=find(E[i].v);
            cnt++;tot+=E[i].w;
            if(!E[i].c)w++;
        }
        if(cnt==v-1)break;
    }
    for(int i=1;i<=e;i++)
        if(!E[i].c)E[i].w-=add;
    return w;
}
int main()
{
    cin>>v>>e>>need;
    for(int i=1;i<=e;i++)
    {
        cin>>E[i].u>>E[i].v>>E[i].w>>E[i].c;
        E[i].u++;E[i].v++;
        if(!E[i].c)wn++;
    }
    int l=-100,r=100;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(kruskal(mid)>=need){l=mid+1;ans=tot-wn*mid;}
        else r=mid-1;
    }
    cout<<ans<<endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/wzxbeliever/p/11714089.html