• 最小生成树


    链接: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;
    } 
  • 相关阅读:
    Dumps for Dummies Dump Analysis Tutorial
    WCF 学习资料
    winform 跨线程设置或读取控件的属性
    反射通过属性名得到属性的值
    C# 不用循环填充数组
    反射字符串调用方法
    使用反射打开窗体,并控制一个窗体只能打开一个
    绘制圆角窗体和圆角panel
    WinForm使用反射通过控件的name得到该控件
    winfrom 绘制圆形按钮
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8438888.html
Copyright © 2020-2023  润新知