ZOJ 3792 Romantic Value(网络流之最小割)(找割边)

题目地址:ZOJ 3792

最小割做的太少。。这题很明显是找割边。找割边就是判断正向弧是否是0.如果跑完一次最小割后正向弧流量为0的话,那就说明这个边为一条割边。但是找到了割边后再怎么办呢。。中午睡觉的时候突然来了灵感。。再利用这些割边求一次最大流不就行了。。把割边的流量都设为1,其他的都为正无穷。那最后的流量就是最少需要的割边了。然后计算就可以了。

这次又把上限值直接设为sink+1了。。。导致WA了12发。。。。。sad。。。以后得注意。。。

代码如下:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
const int INF=0x3f3f3f3f;
int head[100], source, sink, nv, cnt;
int cur[100], num[100], d[100], pre[100];
struct node
{
    int u, v, cap, next;
} edge[1000000];
void add(int u, int v, int cap)
{
    edge[cnt].v=v;
    edge[cnt].cap=cap;
    edge[cnt].next=head[u];
    head[u]=cnt++;

    edge[cnt].v=u;
    edge[cnt].cap=0;
    edge[cnt].next=head[v];
    head[v]=cnt++;
}
void bfs()
{
    memset(num,0,sizeof(num));
    memset(d,-1,sizeof(d));
    queue<int>q;
    q.push(sink);
    d[sink]=0;
    num[0]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].v;
            if(d[v]==-1)
            {
                d[v]=d[u]+1;
                num[d[v]]++;
                q.push(v);
            }
        }
    }
}
int isap()
{
    memcpy(cur,head,sizeof(cur));
    int flow=0, u=pre[source]=source, i;
    bfs();
    while(d[source]<nv)
    {
        if(u==sink)
        {
            int f=INF, pos;
            for(i=source; i!=sink; i=edge[cur[i]].v)
            {
                if(f>edge[cur[i]].cap)
                {
                    f=edge[cur[i]].cap;
                    pos=i;
                }
            }
            for(i=source; i!=sink; i=edge[cur[i]].v)
            {
                edge[cur[i]].cap-=f;
                edge[cur[i]^1].cap+=f;
            }
            flow+=f;
            u=pos;
        }
        for(i=cur[u]; i!=-1; i=edge[i].next)
        {
            if(d[edge[i].v]+1==d[u]&&edge[i].cap)
                break;
        }
        if(i!=-1)
        {
            cur[u]=i;
            pre[edge[i].v]=u;
            u=edge[i].v;
        }
        else
        {
            if(--num[d[u]]==0) break;
            int mind=nv;
            for(i=head[u]; i!=-1; i=edge[i].next)
            {
                if(mind>d[edge[i].v]&&edge[i].cap)
                {
                    mind=d[edge[i].v];
                    cur[u]=i;
                }
            }
            d[u]=mind+1;
            num[d[u]]++;
            u=pre[u];
        }
    }
    return flow;
}
int main()
{
    int n, m, sum, u, v, w, t, k, i, j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d",&n,&m,&source,&sink);
        memset(head,-1,sizeof(head));
        cnt=0;
        sum=0;
        nv=n+1;
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
            sum+=w;
        }
        int x=isap();
        if(x==0)
        {
            printf("Inf\n");
            continue ;
        }
        for(i=0; i<cnt; i+=2)
        {
            if(edge[i].cap==0)
            {
                edge[i].cap=1;
                edge[i^1].cap=0;
            }
            else
            {
                edge[i].cap=INF;
                edge[i^1].cap=0;
            }
        }
        int tot=isap();
        double ans=(sum-x)*1.0/tot;
        printf("%.2lf\n",ans);
    }
    return 0;
}

ZOJ 3792 Romantic Value(网络流之最小割)(找割边)

时间: 2024-10-13 23:37:09

ZOJ 3792 Romantic Value(网络流之最小割)(找割边)的相关文章

ZOJ 3792 Romantic Value(ISAP &amp;&amp; 最小割)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3792 这题是求最小割,但是不会求最小割,龙哥教的权值先*10000+1,利用前向星加边,来储存地图,得到的最大流量/10000,对%10000就是割边   Result Accepted ID  3792 Language  C++ Time  0ms 352KB #include <iostream> #include <cstdlib> #in

zoj 3792 Romantic Value(最小割下边数最小)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5300 大致题意:给出一个无向图,以及起点与终点.要删除一些边使得起点与终点不连通,在删掉边的权值之和最小的情况下要求删除的边数尽量少.求出一个比值:剩余边数权值和/删除的边数. 思路:删除边的权值之和最小显然是求最小割即最大流.但同时要求删除边数最少,解决方法是把边数也加到权值上去,一起求最大流,因为边数最多是1000,即每条边的边权置为 w*10000+1,1代表这一条边.

ZOJ 3792 Romantic Value 最小割+求割边的数量

点击打开链接 Romantic Value Time Limit: 2 Seconds      Memory Limit: 65536 KB Farmer John is a diligent man. He spent a lot of time building roads between his farms. From his point of view, every road is romantic because the scenery along it is very harmon

ZOJ 2587 Unique Attack (判断最小割的唯一性)

ZOJ 2587 Unique Attack 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1587 题意:N 台超级计算机连成一个网络.M 对计算机之间用光纤直接连在一起,光纤的连接是双向的.数据可以直接在有光纤直接连接的计算机之间传输,也可以通过一些计算机作为中转来传输. 有一群恐怖分子计划攻击网络.他们的目标是将网络中两台主计算机断开,这样这两台计算机之间就无法传输数据了.恐怖分子已经计算好了摧毁每条光纤所需要花

HDU 3046Pleasant sheep and big big wolf(网络流之最小割)

题目地址:HDU 3046 最小割第一发!其实也没什么发不发的...最小割==最大流.. 入门题,但是第一次入手最小割连入门题都完全没思路...sad..对最小割的本质还是了解的不太清楚.. 这题就是对每两个相邻的格子的边界都要进行加边,然后求最大流就OK了. RE了好长时间,注意遍历加边的时候要从1开始,而不是0开始,因为0是源点的...(也许只有我才犯这种错误吧...)建图不多说了..只要了解了最小割,建图还是很容易想的. 代码如下: #include <iostream> #includ

POJ 3469 Dual Core CPU(网络流之最小割)

题目地址:POJ 3469 建图思路:建源点与汇点,源点与CPU1相连,汇点与CPU2相连,对共享数据的之间连无向边. 我的ISAP过这题还是毫无时间压力的嘛... 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctyp

【CF331E】Biologist(网络流,最小割)

[CF331E]Biologist(网络流,最小割) 题面 洛谷 翻译: 有一个长度为\(n\)的\(01\)串,将第\(i\)个位置变为另外一个数字的代价是\(v_i\). 有\(m\)个要求 每个要求的形式是 首先确定若干位置都要是\(0\)或者\(1\) 然后给定这\(K\)个位置,如果些位置上都满足要求 那么就可以得到\(W_k\)元 某些要求如果失败了还要倒着给\(g\)元 问最终能够得到的最大利润 输入格式: 第一行是\(n,m,g\) 第二行是\(V_i\) 接下来\(m\)行 第

ZOJ 3792 Romantic Value 最小割(最小费用下最小边数)

求最小割及最小花费 把边权c = c*10000+1 然后跑一个最小割,则flow / 10000就是费用 flow%10000就是边数. 且是边数最少的情况.. #include<stdio.h> #include<string.h> #include<iostream> #include<math.h> #include<algorithm> #include<queue> #include<vector> using

cogs750栅格网络流(最小割)

750. 栅格网络流 ★★☆   输入文件:flowa.in   输出文件:flowa.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] Bob 觉得一般图的最大流问题太难了,他不知道如何解决,于是他想尝试一个简单点的:栅格网络中的最大流问题,这个虽说简单了一点,但对 Bob 来说依旧太难,现在他有个麻烦需要你帮忙:给你一个 N*M 的栅格(如下所示),栅格中的边表示可以流水的管道,边上的数字表示管道的容量,举例说明:在下面图( 2.6.1 )中, (0,0) 和