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

题目大意:给一张网络,问是否存在一条恰为C的流。若不存在,那是否存在一条弧,使得改动这条弧的容量后能恰有为C的流?

题目分析:先找出最大流,如果最大流不比C小,那么一定存在一条恰为C的流。否则,找出最小割集,然后枚举每一条弧改动其容量,看是否存在恰为C的流。

 

代码如下:

# include<iostream>
# include<cstdio>
# include<cmath>
# include<string>
# include<vector>
# include<list>
# include<set>
# include<map>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;

# define LL long long
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CL(a,b) memset(a,b,sizeof(a))
# define CLL(a,b,n) fill(a,a+n,b)

const double inf=1e30;
const int INF=1<<30;
const int maxn=10005;

struct Edge
{
    int fr,to;
    LL cap,fw;
    Edge(int _fr,int _to,LL _cap,LL _fw):fr(_fr),to(_to),cap(_cap),fw(_fw){}
    bool operator <(const Edge &a) const{
        if(fr==a.fr) return to<a.to;
        return fr<a.fr;
    }
};
vector<Edge>edges,tedges,ans;
vector<int>G[2*maxn];
vector<int>minCut;
int N,E,cur[105],vis[105],d[105];
LL C,Flow;
int s,t;

void init()
{
    Flow=0;
    s=1,t=N;
    edges.clear();
    REP(i,0,N+1) G[i].clear();
}

void addEdge(int u,int v,LL c)
{
    edges.push_back(Edge(u,v,c,0));
    edges.push_back(Edge(v,u,0,0));
    int m=edges.size();
    G[u].push_back(m-2);
    G[v].push_back(m-1);
}

bool BFS()
{
    CL(vis,0);
    queue<int>q;
    vis[s]=1;
    d[s]=0;
    q.push(s);
    while(!q.empty()){
        int x=q.front();q.pop();
        REP(i,0,G[x].size()){
            Edge &e=edges[G[x][i]];
            if(!vis[e.to]&&e.cap>e.fw){
                vis[e.to]=1;
                d[e.to]=d[x]+1;
                q.push(e.to);
            }
        }
    }
    return vis[t];
}

LL DFS(int x,LL a)
{
    if(x==t||a==0) return a;
    LL 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.fw)))>0){
            e.fw+=f;
            edges[G[x][i]^1].fw-=f;
            flow+=f;
            a-=f;
            if(a==0) break;
        }
    }
    return flow;
}

bool Dinic()
{
    while(BFS()){
        CL(cur,0);
        Flow+=DFS(s,INF);
        if(Flow>=C) return true;
    }
    return false;
}

void findCut()
{
    minCut.clear();
    for(int i=0;i<edges.size();i+=2){
        Edge &e=edges[i];
        if(vis[e.fr]&&!vis[e.to]) minCut.push_back(i);
    }
}

void toFind()
{
    findCut();
    ans.clear();
    tedges.clear();
    int len=edges.size();
    REP(i,0,len) tedges.push_back(edges[i]);
    LL f=Flow;
    REP(i,0,minCut.size()){
        edges[minCut[i]].cap+=C;
        if(Dinic()) ans.push_back(edges[minCut[i]]);
        Flow=f;
        edges.clear();
        REP(j,0,len) edges.push_back(tedges[j]);
    }
}

void solve(int cas)
{
    printf("Case %d: ",cas);
    if(C==0||Dinic()){
        printf("possible\n");
    }else{
        toFind();
        int len=ans.size();
        if(len>0){
            printf("possible option:");
            sort(ans.begin(),ans.end());
            REP(i,0,len) printf("(%d,%d)%c",ans[i].fr,ans[i].to,(i==len-1)?'\n':',');
        }else
            printf("not possible\n");
    }
}

void read()
{
    int a,b;
    LL c;
    while(E--)
    {
        scanf("%d%d%lld",&a,&b,&c);
        addEdge(a,b,c);
    }
}

int main()
{
    int cas=0;
    while(scanf("%d%d%lld",&N,&E,&C),N|E|C)
    {
        init();
        read();
        solve(++cas);
    }
  return 0;
}

  

转载于:https://www.cnblogs.com/20143605--pcx/p/5027979.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值