`
yzmduncan
  • 浏览: 333036 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

网络流经典模型之——竞赛问题SGU 326 Perspective

阅读更多

    停摆??停摆你妹啊!!2011-2012NBA赛季开已经打啦!你OUT了。

    有n支队伍比赛,n<=20。已经打了一些比赛,并且知道了A赛区的队伍的目前得分。队伍i的目前得分为score[i],剩余比赛场次为remain[i],剩余场次包括同赛区和异赛区的比赛。用match[i][j]表示A区队伍的剩余的比赛情况,i和j剩余的比赛场数。当然,remain[i]>=sigma{match[i][k],1<=k<=n}。要知道,篮球比赛是没有平局的,问队伍1可不可能在赛季末获得A区的第一名(可以并列第一)?

    解:

    1. 显然,有种情况是:当队伍1赢下剩下所有比赛,其余队伍输掉剩余比赛,队伍1也不可能赢得第一。

    2. 增设源点s和汇点t,两类点:左边点代表队伍,右边点代表某两个队伍之间的比赛。

        s到第一类点连边,容量为那支队伍还可以赢得的最多的比赛场数,即(队伍1目前得分+队伍1的剩余比赛场数-队伍i的目前得分);

        第二类点到t连边,容量为该点代表的两只队伍剩余的比赛场数K;

        第一类点到第二类点:若队伍i和队伍j之间有比赛,且对应的第二类点的标号为p,则连边(i,p,INF),(j,p,INF)。

    3. 求最大流。若第二类点到t的边都满流,就可以找到一组解,否则无解。

为何这样建图是对的呢?可以了解到建图的形式为S-->每个队-->比赛-->T,就是把剩余的比赛场数分配到每个队中,每个队的得分不能超过限制。当然这个限制还不够,还需要最小割全部切到与T相连的边上;否则,最小割肯定切到至少两个队伍上的边,而且要打的比赛>0,这样,本来这两个队的得分已经==队伍1的最高得分,再打比赛,肯定会有一个队超过限制,这样队伍1就不肯能获得冠军了。

     复杂度分析:点数最多有2+n+(n+1)*n/2<=232,显然用最大流是合适的。听说有更好的方法。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxv = 1000;
const int maxe = 10000;
int n;
int score[30];
int remain[30];
int match[30][30];
//
struct Edge
{
    int v;
    int next;
    int flow;
};
Edge e[maxe];
int head[maxv],edgeNum;
int now[maxv],d[maxv],vh[maxv],pre[maxv],preh[maxv];

void addEdge(int a,int b,int c)
{
    e[edgeNum].v = b;
    e[edgeNum].flow = c;
    e[edgeNum].next = head[a];
    head[a] = edgeNum++;
    e[edgeNum].v = a;
    e[edgeNum].flow = 0;
    e[edgeNum].next = head[b];
    head[b] = edgeNum++;
}

void Init()
{
    edgeNum = 0;
    memset(head,-1,sizeof(head));
    memset(d,0,sizeof(d));
}

int sap(int s,int t,int n)       //源点,汇点,结点总数
{
    int i,x,y;
    int f,ans = 0;
    for(i = 0; i < n; i++)
        now[i] = head[i];
    vh[0] = n;
    x = s;
    while(d[s] < n)
    {
        for(i = now[x]; i != -1; i = e[i].next)
            if(e[i].flow > 0 && d[y=e[i].v] + 1 == d[x])
                break;
            if(i != -1)
            {
                now[x] = preh[y] = i;
                pre[y] = x;
                if((x=y) == t)
                {
                    for(f = INF,i=t; i != s; i = pre[i])
                        if(e[preh[i]].flow < f)
                            f = e[preh[i]].flow;
                    ans += f;
                    do
                    {
                        e[preh[x]].flow -= f;
                        e[preh[x]^1].flow += f;
                        x = pre[x];
                    }while(x!=s);
                }
            }
            else
            {
                if(!--vh[d[x]])
                    break;
                d[x] = n;
                for(i=now[x]=head[x]; i != -1; i = e[i].next)
                {
                    if(e[i].flow > 0 && d[x] > d[e[i].v] + 1)
                    {
                        now[x] = i;
                        d[x] = d[e[i].v] + 1;
                    }
                }
                ++vh[d[x]];
                if(x != s)
                    x = pre[x];
            }
    }
    return ans;
}
//

int main()
{
    int i,j,k;
    int cnt;
    while(scanf("%d",&n)!=EOF)
    {
        Init();
        cnt = 0;
        for(i = 1; i <= n; i++)
            scanf("%d",&score[i]);
        for(i = 1; i <= n; i++)
            scanf("%d",&remain[i]);
        for(i = 1; i <= n; i++)
            for(j = 1; j <= n; j++)
                scanf("%d",&match[i][j]);
        int high = score[1] + remain[1];
        for(i = 2; i <= n; i++)      //剪枝:1队剩下比赛全赢并且其余队全输,仍不能赢得比赛。
        {
            if(score[i] > high)
                break;
        }
        if(i<=n)
        {
            printf("NO\n");
            continue;
        }
        for(i = 2; i <= n; i++)
            for(j = i+1; j <= n; j++)
                if(match[i][j])
                    cnt++;
        int source = 0;
        int sink = cnt+n+1;
        int flow = 0;
        for(i = 2; i <= n; i++)
            addEdge(source,i,high-score[i]);
        k = 0;
        for(i = 2; i <= n; i++)
        {
            for(j = i+1; j <= n; j++)
            {
                if(match[i][j])
                {
                    ++k;
                    addEdge(i,n+k,INF);
                    addEdge(j,n+k,INF);
                    addEdge(n+k,sink,match[i][j]);
                    flow += match[i][j];
                }
            }
        }
        if(flow == sap(source,sink,sink+1))
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

 

 

 

 

分享到:
评论

相关推荐

    sgu101-121.rar_sgu_sgu101 pascal

    【标题】"sgu101-121.rar_sgu_sgu101 pascal" 指的是一个包含SGU在线评测系统上题目编号从101到121的Pascal语言解题代码的压缩包。SGU(Stepik Graph Problems)是一个专门针对图论和算法问题的在线评测系统,它提供...

    上下界网络流

    "上下界网络流" 上下界网络流是一种特殊的网络流,边的流量有限制,必须在[down, up]的范围内。普通的网络流也是一种特殊的上下界网络流,只是每条边的流量限制为[0, cap]。上下界网络流可以分为两种:有源汇和无...

    SGU离线题库(2015-6-8整理)

    3. **图论问题**:最短路径、最小生成树、拓扑排序、网络流等,这些都是图论在算法中的应用,常用于解决网络连接和资源分配问题。 4. **动态规划**:动态规划是一种强大的求解最优化问题的方法,适用于解决具有重叠...

    SGU推荐题目分类

    176 Flow construction 上下界网络流:Flow construction 是 SGU 中的一道上下界网络流题目,要求使用上下界网络流来解决。 177 Sqare 倒序染色:Sqare 是 SGU 中的一道倒序染色题目,要求使用倒序染色来解决。 ...

    pku sgu 经典图论题解答

    在“pku sgu 经典图论题解答”中,我们可以期待找到一系列针对图论问题的深入解析和高效解决方案。这些题目可能涵盖了一些基本概念,如图的定义、连通性、欧拉路径、哈密顿回路,以及更高级的主题,如最短路径算法...

    SGU题库整合 Volume (200 - 299) pdf版

    - **背景**: 汉诺塔问题是一个经典的递归问题。 - **问题描述**: 探讨汉诺塔问题的变种,比如增加盘子的数量或改变移动规则等。 - **解决方案**: 1. **递归算法**: 利用递归的思想解决问题。 2. **优化策略**: ...

    SGU 390 AC源码

    SGU 390 AC源码,数位统计的难题

    SGU离线题库(完整530道题,带试题难度排序)

    SGU离线题库是一个为编程爱好者和竞赛程序员精心整理的资源,包含了完整的530道题目,每道题目都来自于著名的在线编程平台SGU(SPOJ Global Users)。这个题库不仅提供了丰富的编程挑战,还特别加入了试题的难度排序...

    SGU 385 AC程序

    SGU 385,我写的程序,一道DP题,跟概率有关

    SGU-801综合通讯接入装置使用说明书

    SGU-801 综合通讯接入装置使用说明书 SGU-801 综合通讯接入装置是由许继电气股份有限公司出品的一款综合通讯接入装置,主要用于提供通讯接入服务。下面是对 SGU-801 综合通讯接入装置的技术指标和工作原理的详细...

    sgu:acm.sgu.ru

    【标题】"sgu:acm.sgu.ru" 指的是一个与 ACM(国际计算机科学联盟)相关的项目,特别是与 acm.sgu.ru 这个在线编程竞赛平台相关。这个平台是为程序员提供练习和参与算法竞赛的地方,通常会发布一系列的编程问题,...

    acm pku spoj sgu 经典 图论题解题报告

    sgu176 有源汇的上下界 求最小满足的流 poj 2230 递归求欧拉回路 poj 2985 bst模板 poj2723 2-sat验证,二分答案 poj2455 dinic (ek会超时) hdu1689 求最小奇数环 poj2391 isap最快,dinic不减枝会超时 poj2455 ...

    Acm竞赛常用算法与数据结构.ppt

    ACM/ICPC是由美国计算机学会(ACM)主办的一项国际性大学生编程竞赛,旨在提升学生的编程能力和问题解决技巧。IBM自1998年起成为该赛事的主要赞助商,使得比赛规模不断扩大,影响力日益增强。 竞赛通常由三人团队...

    SPOJ.zip_SPOJ_sgu_them

    "SPOJ.zip_SPOJ_sgu_them"这个压缩包文件就包含了针对SPOJ上的一些问题的解决方案,特别的是,所有这些解决方案都采用了动态规划(Dynamic Programming, 简称DP)这一强大的算法思想。下面我们将深入探讨动态规划...

    SGU103AC代码

    SGU 103AC 代码 质量有保证!

    SGU 333 AC源码

    SGU 333 集训队AC程序,秒过,CPP

    Acm竞赛常用算法与数据结构_推荐下载!!!

    ACM竞赛是由美国计算机学会(Association for Computing Machinery)主办的一项全球性赛事,旨在提升大学生在分析和解决实际问题上的技能,同时也是培养未来IT精英的重要平台。 在竞赛中,参赛队伍通常由三名队员组成...

    sgu-maven250303

    sgu-maven250303是一个与Java编程语言密切相关的项目构建工具。在Java开发过程中,Maven是广泛使用的工具之一,它帮助开发人员自动化构建过程,从编译、测试到打包应用程序。使用Maven,开发者能够简化依赖管理、...

    SGU题库 (100-199) pdf版

    ### SGU题库 (100-199) 知识点概览 #### 100. A+B **题目概述:** 这是一道基础的数学计算题,要求求解两个整数A和B的和。 **知识点:** - 基本的算术运算:加法。 - 输入输出格式:如何正确读取输入数据并输出...

    SGU DownloadScheduler-开源

    "SGU DownloadScheduler"是一个专为低带宽环境设计的开源下载管理工具。这个软件的主要目标是通过智能调度策略在全天候范围内优化下载过程,从而最大化利用有限的网络资源。作为一个开源项目,它允许用户查看并修改...

Global site tag (gtag.js) - Google Analytics