UVA 11248 Frequency Hopping (最大流+最小割)

题意:与正常的网络流一样,不过给定的第一行的最后一个数C的意思是能能否在给定的图里求出修改某一条边或者不修改某一条边是的这个图的流变成C,如果没修改就能有C,那么输出possible,通过修改能得到C输出possible+能修改的边集合,否则输出no possible

思路:(自己的是死暴力方法,直接爆了,想了很多法子都来不起,最后参照白书的思路来起了)可以先求出最大流,然后求出最小割里的弧,依次修改最小割里的弧,看能求出的最大流是否大于C

PS:不优化的话很容易超时,第一个优化是把第一次求得得最大流保存下来,在第一次次最大流得基础上增广;第二个优化是求出当前的流到达C就可以了

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;

#define maxn 110
#define maxm 22010
typedef long long ll;
#define INF 0x3f3f3f3f
#define cl(x,v); memset(x,v,sizeof(x));

struct Edge{
    int from,to,cap,flow;
};

bool cmp(const Edge& a,const Edge& b)
{
    return a.from < b.from||(a.from==b.from&&a.to<b.to);
}

struct Dinic{
    int n,m,s,t;
    vector<Edge>edges;
    vector<int>g[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxm];
    void init(int n)
    {
        this->n=n;
        for(int i=0;i<=n;i++)g[i].clear();
        edges.clear();
    }
    void AddEdge(int from,int to,int cap)
    {
        edges.push_back((Edge){from,to,cap,0});
        edges.push_back((Edge){to,from,0,0});
        m=edges.size();
        g[from].push_back(m-2);
        g[to].push_back(m-1);
    }
    bool BFS()
    {
        cl(vis,0);
        queue<int>q;
        q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            for(int i=0;i<g[x].size();i++)
            {
                Edge& e=edges[g[x][i]];
                if(!vis[e.to]&&e.cap>e.flow)
                {
                    vis[e.to]=1;
                    d[e.to]=d[x]+1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int DFS(int x,int a)
    {
        if(x==t||a==0)return a;
        int flow=0,f;
        for(int& i=cur[x];i<g[x].size();i++)
        {
            Edge& e=edges[g[x][i]];
            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0)
            {
                e.flow+=f;
                edges[g[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0)break;
            }
        }
        return flow;
    }
    int Maxflow(int s,int t,int need)
    {
        this->s=s;
        this->t=t;
        int flow=0;
        while(BFS())
        {
            cl(cur,0);
            flow+=DFS(s,INF);
            if(flow>need)return flow;
        }
        return flow;
    }
    vector<int> Mincut()
    {
        BFS();
        vector<int>ans;
        for(int i=0;i<edges.size();i++)
        {
            Edge& e=edges[i];
            if(vis[e.from]&&!vis[e.to]&&e.cap>0)
                ans.push_back(i);
        }
        return ans;
    }
    void Reduce()
    {
        for(int i=0;i<edges.size();i++)
            edges[i].cap-=edges[i].flow;
    }
    void ClearFlow()
    {
        for(int i=0;i<edges.size();i++)
            edges[i].flow=0;
    }
};

Dinic solver;
int main()
{
    int N,E,C,cas=0;
    while(scanf("%d%d%d",&N,&E,&C)!=EOF)
    {
        if(N==0)break;
        solver.init(N);
        int a,b,c;
        while(E--)
        {
            scanf("%d%d%d",&a,&b,&c);
            solver.AddEdge(a,b,c);
        }
        int flow=solver.Maxflow(1,N,INF);
        printf("Case %d: ",++cas);
        if(flow>=C)printf("possible\n");
        else
        {
            vector<int>cut=solver.Mincut();
            solver.Reduce();
            vector<Edge>ans;
            for(int i=0;i<cut.size();i++)
            {
                Edge& e=solver.edges[cut[i]];
                int temp=e.cap;
                e.cap=C;
                solver.ClearFlow();
                if(flow+solver.Maxflow(1,N,C-flow)>=C)ans.push_back(e);
                e.cap=temp;
            }
            if(ans.empty())printf("not possible\n");
            else
            {
                sort(ans.begin(),ans.end(),cmp);
                printf("possible option:(%d,%d)",ans[0].from,ans[0].to);
                for(int i=1;i<ans.size();i++)
                    printf(",(%d,%d)",ans[i].from,ans[i].to);
                printf("\n");
            }
        }
    }
    return 0;
}
时间: 2024-12-26 11:01:32

UVA 11248 Frequency Hopping (最大流+最小割)的相关文章

Uvaoj 11248 Frequency Hopping(Dinic求最小割)

题意:1到n节点(节点之间有一定的容量),需要流过C的流量,问是否可以?如果可以输出possible, 否则如果可以扩大任意一条边的容量 可以达到目的,那么输出possible option:接着输出每一条可以达到目的的边(按升序),再否则输出not possible 思路:先求一次最大流,如果流量至少为C,则直接输出possible,否则需要修改的弧一定在最小割里! 接着吧这些弧(最小割里的)的容量设为无穷大,然后在求最大流,看最大流的流量能否满足是C即可,如果满足了,那就把这一条边记录下来

uva 11248 Frequency Hopping (最大流)

uva 11248 Frequency Hopping 题目大意:给定一个有向网络,每条边均有一个容量. 问是否存在一个从点1到点N.流量为C的流.假设不存在,能否够恰好改动一条弧的容量,使得存在这种流. 解题思路:先依照题目给出的边建好图,然后跑一发最大流,得到原始最大流C1,假设C1==C或者C==0时.能够直接输出possible.假设不存在这种流.那么開始找割边,将这些割边的容量添加C,再求最大流.假设能够,那么要输出全部的方案.改动全部割边后,仍没有符合条件的流,输出 not poss

UVA 11248 - Frequency Hopping(网络流)

UVA 11248 - Frequency Hopping 题目链接 题意:给定一个网络,现在需要从1到N运输流量C,问是否可能,如果可能输出可能,如果不可能,再问是否能通过扩大一条边的容量使得可能,如果可以输出这些边(按u先排再按v排),如果不行输出不可能 思路:先做一遍网络流,然后每次在最小割上进行增加容量,需要两个优化,每次找流量找到>= c就可以了,然后每次修改容量,可以直接从之前做过的网络流继续做即可 代码: #include <cstdio> #include <cst

UVA 11248 Frequency Hopping

Frequency Hopping Time Limit: 10000ms Memory Limit: 131072KB This problem will be judged on UVA. Original ID: 1124864-bit integer IO format: %lld      Java class name: Main 20th July, 1942 Colonel Al Pacheno,According to the previous order “ref:   23

zoj3792--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 harmonious an

最大流-最小割 MAXFLOW-MINCUT ISAP

简单的叙述就不必了. 对于一个图,我们要找最大流,对于基于增广路径的算法,首先必须要建立反向边. 反向边的正确性: 我努力查找了许多资料,都没有找到理论上关于反向边正确性的证明. 但事实上,我们不难理解,对于每条反向边,我们流过它相当于撤销了一条正向边的流量. 并且它是必须的: 而且从理论上,我们在加入反向边之后得到的最大流,我们从残余网络考虑. 我们要认识到,反向边不会使最大流流量减少,这是很显然的.有flow<=flow'. 接下来我们考虑所有点的流量是否可以只用正向边得到. 并且我们考察汇

hdu 3987 Harry Potter and the Forbidden Forest【网路流最小割模型】

Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1549    Accepted Submission(s): 528 Problem Description Harry Potter notices some Death Eaters try to slip

最大流, 最小割问题及算法实现

最大流(MaxFlow)问题 给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capacity),求满足条件的从S到T的最大流(MaxFlow). 想象一条多条不同水流量的水管组成的网络, s为供水广, t为水用户, 最大流问题就是找到能够在s到t流通的最大水流量 一个流是最大流当且仅当其残存网络不包含任何增广路径(里面的名称在后面有详细解释) 流(Flow)的基本性质 设$C_{uv}$代表边u到v最大允许流量(Capacity), $f

bzoj1412-网络流最小割

狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆.可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已.所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养. 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变