哈理工OJ 1491 游河(网络流水题【Edmond-Karp算法】)

题目链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1491

游河
Time Limit: 1000 MS Memory Limit: 65535 K
Total Submit: 143(42 users) Total Accepted: 85(37 users) Rating: Special Judge: No
Description
假期,Hrbust集训队在Tang长老的带领下去河上坐船游玩。 但是很多队员想单独坐船游览风光,体验一个人的旅行。 但是教主说那样会很危险,而且似乎也没那么多的旅行路线。可是队员们还是坚持自己的想法,于是教主提了个要求:如果游览的路线足够一人一条,而且每条路线没有重复的水路的话,就同意大家的做法,不然,Tang长老就请大家集体吃冰棍,一起坐船去。

集训队这次一共去了 D 个人,(1<=D<=200),已知河道上一共N个河叉(2<=N<=200),大家都是从1号位置开始旅行的,终点为第 N 号位置,现在已知道在这N个位置之间有 M 条连通的水路(2<=M<=40000)。

请帮大家计算下存在的路线数是否够大家单人旅行的。

Input
Line 1: 河叉总数 N,道路总数 M,集训队人数 D。

Line 2…M+1:两个整数 A,B,表示位置 A 和 B 之间有一条直接连通的水路。

Output
Line1:如果存在的路径数够大家单人旅行(路径数>= D),输出“Orz!”,否则输出“Jiao Zhu v5!”。

Sample Input
2 2 1

1 2

1 2

7 9 5

1 2

2 3

3 7

1 4

4 3

4 5

5 7

1 6

6 7

Sample Output
Orz!

Jiao Zhu v5!

【题目分析】建图求最大流,然后与总人数相比较,然后看那个大就可以了。

【AC代码】

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INT_MAX 0x3fffffff
const int MAXN=210;
int map[MAXN][MAXN],n,p[MAXN];//map:邻接数组;n:点数;p:前驱数组;
bool EK_bfs(int start,int end)//广度优先算法寻找增光路
{
    queue<int>que;//广度优先搜索队列
    bool flag[MAXN];//标记数组
    memset(flag,false,sizeof(flag));
    memset(p,-1,sizeof(p));//初始化
    que.push(start);
    flag[start]=true;
    while(!que.empty())
    {
        int e=que.front();
        if(e==end)
        {
            return true;
        }
        que.pop();
        for(int i=1;i<=n;i++)
        {
            if(map[e][i]&&!flag[i])
            {
                flag[i]=true;
                p[i]=e;
                que.push(i);
            }
        }
    }
    return false;
}

int EK_Max_Flow(int start,int end)
{
    int u,flow_ans=0,mn;
    while(EK_bfs(start,end))
    {
        mn=INT_MAX;
        u=end;
        while(p[u]!=-1)
        {
            mn=min(mn,map[p[u]][u]);
            u=p[u];
        }
        flow_ans+=mn;
        u=end;
        while(p[u]!=-1)
        {
            map[p[u]][u]-=mn;
            map[u][p[u]]+=mn;
            u=p[u];
        }
    }
    return flow_ans;
}

int main()
{
    int m,k;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        memset(map,0,sizeof(map));
        int u,v;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            map[u][v]+=1;
            map[v][u]+=1;
        }
        int ans=EK_Max_Flow(1,n);
        if(ans>=k)
        {
            printf("Orz!\n");
        }
        else
        {
            printf("Jiao Zhu v5!\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值