最小生成树

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2561

题解:

这题竟然是网络流。。。

考虑kruskal,先把比x小的边加入,只有在此之前u,v不连通那么才有用,所以其实就是最小割

大的边同理

两次答案相加就是结果(因为两次删的边不会重复)

网络流也算是改变认知了,,知道思路只剩建图模板

#include <bits/stdc++.h>
using namespace std;
#define maxn 500000
#define INF 1e9
struct ree{
    int a,b,c,flow;
}a[maxn];
struct re{
    int a,b,c;
}c[maxn],b[maxn];
bool vis[maxn/2];
int l,n,m,a1,b1,l1,s,t,head[maxn],d[maxn];
bool cmp1(re a,re b)
{
    return(a.c<b.c);
}
bool cmp2(re a,re b)
{
    return(a.c>b.c);
}
void arr(int x,int y,int z,int flow)
{
    a[++l].a=head[x];
    a[l].b=y;
    a[l].c=z;
    a[l].flow=flow;
    head[x]=l;
}
bool bfs(){
    memset(vis,0,sizeof(vis));
    queue<int> q;
    q.push(s);
    d[s]=0; vis[s]=1;
    while (!q.empty())
    {
        int x=q.front();q.pop();
        int u=head[x];
        while (u)
        {
            int v=a[u].b;
            if (!vis[v]&&a[u].c>a[u].flow)
            {
                vis[v]=1;
                d[v]=d[x]+1;
                q.push(v);
            }
            u=a[u].a;
        }
    }
    return(vis[t]);
}
int dfs(int x,int y)
{
    if (x==t||y==0) return y;
    int flow=0,f,tmp;
    int u=head[x];
    while (u)
    {
        int v=a[u].b;
        if (d[x]+1==d[v]&&(f=dfs(v,min(y,a[u].c-a[u].flow)))>0)
        {
            a[u].flow+=f;
            if (u%2) tmp=u+1; else tmp=u-1;
            a[tmp].flow-=f;
            flow+=f; 
            y-=f;
            if (y==0) break;
        }
        u=a[u].a;
    }
    return(flow);
}
int maxflow()
{
    int flow=0;
    while (bfs())
    {
        flow+=dfs(s,INF);
    }
    return(flow);
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=m;i++)
      cin>>c[i].a>>c[i].b>>c[i].c;
    memcpy(b,c,sizeof(c));
    sort(c+1,c+m+1,cmp1); sort(b+1,b+m+1,cmp2);
    cin>>a1>>b1>>l1;
    s=a1;t=b1;
    for (int i=1;i<=m;i++)
      if (c[i].c>=l1) break;
      else {
          arr(c[i].a,c[i].b,1,0);
          arr(c[i].b,c[i].a,1,0);
      }
    int ans=maxflow();
    memset(head,0,sizeof(head)); l=0;
    for(int i=1;i<=m;i++)
      if (b[i].c<=l1) break;
      else{
          arr(b[i].a,b[i].b,1,0);
          arr(b[i].b,b[i].a,1,0);
      }
    ans+=maxflow();
    cout<<ans<<endl;
    return 0;
} 
原文地址:https://www.cnblogs.com/yinwuxiao/p/8438888.html