HDU 3452 Bonsai | 最小割

来源:互联网 发布:最大公约数c语言算法 编辑:程序博客网 时间:2024/06/06 11:43

这题让我很清楚得看到最小割的本质,实际就是用最小的代价,使得包含s的大S和包含t的大T分开。

最小代价就是所要求的最小割。

————————————————————————————————————————————————

题意:

给你一棵树,root根节点已经知道。每条边都有一个边权。让你用最小的代价使得根节点与叶子结点分开。


思路:

root节点作为源点s;

叶子节点连到汇点t,容量为INF;

其他节点就根据题目所给数据构建。


此外要找出哪个才是叶子结点,这个我用了dfs来搜。其实可以用一开始就用vecotr来保存邻接表,然后直接判断就可以得知。

————————————————————————————————————————————————

注意点:

流量可以为0,以及只有一个节点的情况。

————————————————————————————————————————————————

#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <queue>#include <vector>#define debug cout<<"debug"<<endl;using namespace std;const int MAXEDGE = 5*1e5+ 5;const int MAXN = 1010;const int INF = 0x3F3F3F3F;int n, r;struct Edge{        int to, cap, flow, next;};Edge edge[MAXEDGE];struct Dinic{        int s, t, pp;        bool vis[MAXN];        int head[MAXN];        int d[MAXN], cur[MAXN];        Dinic(int ss, int tt)        {                s = ss, t = tt;                pp = 0;                memset(head, -1, sizeof(head));                memset(vis, false, sizeof(vis));    //一定要加!        }        void addEdge(int u, int v, int c)        {                edge[pp] = (Edge){v, c, 0, head[u]};                head[u] = pp++;                edge[pp] = (Edge){u, 0, 0,head[v]};                head[v] = pp++;        }        void findLeaves(int u)  //dfs        {                int cnt = 0;                int next = head[u];                vis[u] = true;                while(next != -1)                {                        Edge &e = edge[next];                        if(vis[e.to])                        {                            next = e.next;                            continue;                        }                        //vis[e.to] = true;                        cnt ++;                        findLeaves(e.to);                        next = e.next;                }                if(cnt == 0)                {                        //cout<<"u = "<<u<<endl;                        addEdge(u, t, INF);                }        }        int getMaxFlow()        {                int res = 0;                while(bfs())                {                    for(int i = 0;i < n + 5; i++)                        cur[i] = head[i];                    //cout<<"res = "<<res<<endl;                    res += dfs(s, INF);                }                return res;        }        bool bfs()        {                memset(vis, false, sizeof(vis));                d[s] = 0;                vis[s] = true;                queue <int> q;                q.push(s);                while(!q.empty())                {                        int u = q.front();                        q.pop();                        int next = head[u];                        while(next != -1)                        {                                Edge &e = edge[next];                                if(!vis[e.to] && e.cap > e.flow)                                {                                        d[e.to] = d[u] + 1;                                        vis[e.to] = true;                                        q.push(e.to);                                }                                next = e.next;                        }                }                return vis[t];        }        int dfs(int u, int a)        {                if(u == t || a == 0)    return a;                int &next = cur[u];                int flow = 0, f;                while(next != -1)                {                        Edge &e = edge[next];                        if(d[e.to] == d[u] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0)                        {                                e.flow += f;                                edge[next^1].flow -= f;                                flow += f;                                a -= f;                                if(a == 0)      break;                        }                        next = e.next;                }                //cout<<"flow = "<<flow<<endl;                return flow;        }};int main(){        while(scanf("%d%d",&n, &r), n&&r)        {                int u, v, c;                int s = r, t = 0;                Dinic dinic(s, t);                for(int i = 0;i < n-1; i++)                {                        scanf("%d%d%d",&u, &v, &c);                        dinic.addEdge(u, v, c);                        dinic.addEdge(v, u, c);                }                if(n == 1)                {                    puts("0");                    continue;                }                dinic.findLeaves(s);                printf("%d\n",dinic.getMaxFlow());        }        return 0;}




































0 0