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

竞赛问题升级版——ZOJ3348

阅读更多

    在上一篇中已经介绍了一种利用网络流求解竞赛问题的解法,构图共有n^2个点。但当比赛队伍逐渐增大时,比如n=60,就会有3600个点,采用网络流显然效率不高。这里再介绍一种更简单的建模方式。

    解:

    1. 还是假设DD赢下剩下的所有比赛,最高得分为high。

    2. 对于剩下的比赛,随意定胜负。记录每位选手的得分score[i],用champ[i][j]表示i赢j的次数。

    3. 增设源点和汇点,三类边:

       边(s,i,score[i]),表示选手i有score[i]次胜利(比赛)要分配。

       边(i,sink,high-1),表示选手i最多的胜利场数不能超过DD。

       边(i,j,champ[i][j])。这是最关键的,也是前面为什么可以任意定胜负。若从s流到点i的流量流到t,说明选手i赢了比赛;若流到j,表示该场胜利被j夺走,即j赢得比赛,所以上面说的假设仅仅是假设。

    4. 判断与s相连的边是否满流,若否则无解。

   复杂度:仅有n+2个点。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <string>
using namespace std;
const int INF = 0x7fffffff;
const int maxv = 60;
const int maxe = 15000;
int score[55];
int champ[55][55];

//
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;
    int n,m;
    int p;
    int k;
    int seq1,seq2;
    char p1[15],p2[15],result[10];
    map<string,int> mp;
    map<string,int>::iterator it;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        k = 0;
        Init();
        mp.clear();
        memset(score,0,sizeof(score));
        memset(champ,0,sizeof(champ));
        mp["DD"] = 0;
        for(i = 0; i < m; i++)
        {
            scanf("%s %s %s",p1,p2,result);
            it = mp.find(p1);
            if(it == mp.end())
            {
                seq1 = ++k;
                mp[p1] = seq1;
            }
            else
                seq1 = it->second;
            it = mp.find(p2);
            if(it == mp.end())
            {
                seq2 = ++k;
                mp[p2] = seq2;
            }
            else
                seq2 = it->second;
            if(result[0] == 'w')
                score[seq1]++;
            else
                score[seq2]++;
        }
        scanf("%d",&p);
        for(i = 0; i < p; i++)
        {
            scanf("%s %s",p1,p2);
            it = mp.find(p1);
            if(it == mp.end())
            {
                seq1 = ++k;
                mp[p1] = seq1;
            }
            else
                seq1 = it->second;
            it = mp.find(p2);
            if(it == mp.end())
            {
                seq2 = ++k;
                mp[p2] = seq2;
            }
            else
                seq2 = it->second;
            //假设序号小的赢得比赛
            if(seq1 > seq2)
                swap(seq1,seq2);
            score[seq1]++;
            champ[seq1][seq2]++;
        }
        it = mp.find("DD");
        if(it == mp.end())
        {
            if(n == 1)
                printf("Yes\n");
            else
                printf("No\n");
            continue;
        }
        int source = 0;
        int sink = k+1;
        int sum = 0;
        for(i = 1; i <= k; i++)
        {
            sum += score[i];
            addEdge(source,i,score[i]);
            addEdge(i,sink,score[0]-1);
            for(j = i+1; j <= k; j++)
            {
                if(champ[i][j])
                    addEdge(i,j,champ[i][j]);
            }
        }
        if(sum == sap(source,sink,sink+1))
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

 

 

 

分享到:
评论

相关推荐

    zoj 1140-zju 2433 简单题的部分答案

    标题 "zoj 1140-zju 2433 简单题的部分答案" 暗示了这是一个关于编程竞赛题目的解答集合,其中涵盖了ZOJ(浙江大学在线评测系统)上的两道题目——ZOJ 1140 和 ZJU 2433。这些题目可能属于算法或数据结构的范畴,...

    zoj1027解题指南

    【标题】"ZOJ1027解题指南"是一个针对特定编程竞赛题目——ZOJ1027的解决方案集合。ZOJ,全称为“Zhejiang Online Judge”,是浙江大学主办的一个在线编程竞赛平台,提供了丰富的算法题目供参赛者练习和挑战。本解题...

    zoj 1002_zoj1002_

    【标题】"ZOJ 1002" 是一个在线编程竞赛题目,源自ZOJ(Zhejiang Online Judge),这是一个面向ACM/ICPC(国际大学生程序设计竞赛)的在线评测系统。题目编号1002,通常表示该题是ZOJ平台上的一个问题,可能涉及算法...

    zoj 源码700题

    【标题】"zoj 源码700题"是指一个包含700多道ZOJ(在线判题系统Zhejiang Online Judge)编程竞赛题目的源代码集合。这个资源对于学习算法、提高编程技能以及准备编程竞赛的学员来说极具价值。 【描述】"包含了zoj...

    ZOJ:浙江大学程序在线评测系统.docx

    ZOJ,全称“浙江大学程序在线评测系统”(Zhejiang University Online Judge),是一个提供信息学(算法竞赛)题库及程序评测的网站。以下是关于ZOJ的详细介绍: 一、基本信息 名称:浙江大学程序在线评测系统(ZOJ)...

    ZOJ.zip_Jugs A_ZOJ NTA_zoj acm_zoj acm 1216_zoj code

    【Jugs A】可能是指ZOJ中的一个特定问题,通常在ACM竞赛中,题目会被分为不同的难度等级,"A"可能是代表初级或简单的级别。这个问题可能涉及到实际生活中的数学问题,比如水壶倒水的问题,需要通过编程来解决如何将...

    zoj.gz_ ZOJ_ZOJ 1016_max flow_zoj 1045_zoj.rar

    标题中的"ZOJ.gz_ ZOJ_ZOJ 1016_max flow_zoj 1045_zoj.rar" 提到了两个ZOJ(Zhejiang Online Judge)的题目,分别是1016和1045,这两个数字通常代表在线编程竞赛中的题目编号。这些题目通常涉及到算法和数据结构的...

    zoj.rar_zoj_zoj4041

    《ZOJ 4041问题的正确解法与程序分析》 ZOJ(Zhejiang Online Judge)是一个知名的在线编程竞赛平台,其中的题目编号为4041...希望这篇文章能为你提供一个分析和学习ZOJ 4041问题的框架,激发你在编程竞赛中的创造力。

    ZOJ4.16.rar_zoj

    ZOJ4.16.rar_zoj 是一个与ZOJ(Zhejiang Online Judge)相关的压缩文件,这通常意味着它包含了某次程序设计竞赛,特别是2004年4月16日浙江省程序设计竞赛的题目。ZOJ是浙江大学主办的一个在线编程平台,它允许参赛者...

    pku hdu zoj题目分类

    本资料包聚焦于三大OJ平台——PKU(北京大学)、HDOJ(杭州电子科技大学)和ZOJ(浙江大学),它们都提供了丰富的题目资源,尤其是针对不同算法的分类,对于学习和准备ACM(国际大学生程序设计竞赛)或者其他算法...

    ZOJ题目答案源码

    ZOJ(Zhejiang Online Judge)是一个著名的在线编程竞赛平台,主要面向计算机科学与信息技术的学生和爱好者,提供了大量的算法题目供参赛者练习和提交代码。"ZOJ题目答案源码"是一个压缩包文件,其中包含了700多道...

    ZOJ题解集合-截至2835

    ZOJ(Zhejiang Online Judge)是一个著名的在线编程竞赛平台,尤其在ACM(国际大学生程序设计竞赛)领域中有着广泛的影响力。这个“ZOJ题解集合-截至2835”显然是一份包含了大量ZOJ题目解决方案的压缩包,其中涵盖了...

    zoj 700源代码

    ZOJ,全称为Zhejiang Online Judge,是一个知名的在线编程竞赛平台,主要服务于浙江大学和国内其他高校的学生,提供丰富的算法题目供参赛者练习和比赛。这个压缩包文件名为"ZOJ 700多题源代码",意味着它包含了解决...

    ZOJ月赛 题解 (ZOJ Monthly, August 2014)

    2014年8月的ZOJ月赛是一场面向广大编程爱好者的竞赛,该赛事涵盖了多种算法和数据结构问题,旨在挑战参赛者的编程思维和问题解决能力。 资源中的解题报告和代码是参赛者或高手们对比赛中题目所作的详细解答和实现,...

    zoj2536.rar_zoj25

    标题 "zoj2536.rar_zoj25" 暗示这是一份与ZOJ(中国大学在线编程竞赛)第2536号问题相关的提交文件,可能包含了参赛者或教练的代码解决方案。描述中的“这个不是用贪心做的”表明该问题可能涉及到一种非贪心算法的...

    ZOJ1014.zip_zoj code_zoj1004

    ZOJ是面向编程爱好者和学生的一个在线编程竞赛平台,它提供了各种算法和数据结构的问题供用户解决并提交代码进行测试。 描述中的“枫教授在一所大学教数学,他发现了一个函数,用于获得一个表达式的操作数的目的,...

    浙江大学ZOJ题目分类

    浙江大学ZOJ(Zhejiang University Online Judge)是一个在线编程练习平台,主要服务于计算机科学和技术的学习者,特别是对算法和编程有浓厚兴趣的学生。这个平台提供了大量的编程题目,涵盖了各种难度和主题,帮助...

    zoj3464 Rugby Football测试数据

    根据提供的标题和描述“ZOJ 3464 Rugby Football 测试数据”,我们可以了解到这是针对ZOJ(Zhejiang University Online Judge)平台上的一个编号为3464的问题——Rugby Football 的测试数据。在编程竞赛中,测试数据...

    zoj 题库 详细解答 解题代码

    zoj 题库 详细解答 解题代码 该资源主要涵盖了 zoj 题库中的各种编程题目,涵盖了基本算法、数据结构、数学运算等多个方面的知识点。下面是对该资源中出现的知识点的详细解释: 1. 第一次 ACM 总结(7th ACM) 该...

    zoj代码集合

    【ZOJ代码集合】是一个专为ACM(国际大学生程序设计竞赛)爱好者准备的资源库,其中包含了丰富的算法实现和编程技巧。这个压缩包文件名“ZOJ入门与提高代码集”暗示了它旨在帮助初学者逐步提升编程能力,同时也为有...

Global site tag (gtag.js) - Google Analytics