zoukankan      html  css  js  c++  java
  • 洛谷 P3931 SAC E#1

    洛谷 P3931 SAC E#1 - 一道难题 Tree

    洛谷传送门

    题目背景

    冴月麟和魏潇承是好朋友。

    题目描述

    冴月麟为了守护幻想乡,而制造了幻想乡的倒影,将真实的幻想乡封印了。任何人都无法进入真实的幻想乡了,但是她给前来救她的魏潇承留了一个线索。

    她设置了一棵树(有根)。树的每一条边上具有割掉该边的代价。

    魏潇承需要计算出割开这棵树的最小代价,这就是冴月麟和魏潇承约定的小秘密。

    帮帮魏潇承吧。

    注:所谓割开一棵有根树,就是删除若干条边,使得任何任何叶子节点和根节点不连通。

    输入格式

    输入第一行两个整数n,S表示树的节点个数和根。

    接下来n-1行每行三个整数a、b、c,表示a、b之间有一条代价为c的边。

    输出格式

    输出包含一行,一个整数,表示所求最小代价。


    题解:

    题意就很像最小割裸题。但是最小割只要求汇点与源点不联通,这道题要求所有叶子节点都不连通。很容易啊,建超级汇点就好了。

    然后根据最大流最小割定理,直接在上面跑Dinic最大流。

    代码:(不知道为什么,这份代码会MLE一半的点,如有大佬请指正)

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn=1e5+5;
    const int INF=1e9;
    int n,s,t,ans;
    int tot=1,head[maxn],nxt[maxn<<1],to[maxn<<1],val[maxn<<1];
    int lv[maxn],cur[maxn];
    bool v[maxn];
    queue<int> q;
    void add(int x,int y,int z)
    {
        to[++tot]=y;
        nxt[tot]=head[x];
        val[tot]=z;
        head[x]=tot;
    }
    void dfs_pre(int x,int f)
    {
        bool flag=0;
        for(int i=head[x];i;i=nxt[i])
        {
            int y=to[i];
            if(y==f)
                continue;
            flag=1;
            dfs_pre(y,x);
            val[i^1]=0;
        }
        if(!flag)
        {
            add(x,t,INF);
            add(t,x,0);
        }
    }
    bool bfs()
    {
        memset(lv,0,sizeof(lv));
        lv[s]=1;
        q.push(s);
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            for(int i=head[x];i;i=nxt[i])
            {
                int y=to[i];
                if(!val[i]||lv[y])
                    continue;
                lv[y]=lv[x]+1;
                q.push(y);
            }
        }
        return lv[t];
    }
    int dfs(int x,int flow)
    {
        if(!flow||x==t)    
            return flow;
        int re=0;
        for(int i=cur[x];i;i=nxt[i])
        {
            cur[x]=i;
            int y=to[i];
            if(val[i]>0 && lv[y]==lv[x]+1)
            {
                int tmp=dfs(y,min(val[i],flow));
                if(!tmp)
                    continue;
                flow-=tmp;
                re+=tmp;
                val[i]-=tmp;
                val[i^1]+=tmp;
            }
        }
        return re;
    }
    int main()
    {
        scanf("%d%d",&n,&s);
        t=n+1;
        for(int i=1;i<n;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        dfs_pre(s,-1);
        while(bfs())
        {
            memcpy(cur,head,sizeof(head));
            ans+=dfs(s,INF);
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    安卓手机无法使用adb导出文件
    dex2jar 报错 com.googlecode.d2j.DexException: not support version
    夜神模拟器adb连接
    无法安装 /lib/x86_64-linux-gnu/libpng12.so.0 的新版本: 没有那个文件或目录
    mysql基础 -创建
    VScode
    阿强的TypeScript基础
    Vue由浅入深之Array变化侦测
    深入浅出Vue.js一之Object的变化侦测
    阿强工作中常用的js的数组方法汇总
  • 原文地址:https://www.cnblogs.com/fusiwei/p/14056284.html
Copyright © 2011-2022 走看看