zoukankan      html  css  js  c++  java
  • 友谊赛

    题目:

    【问题描述】

          大COS所在的FC幽寂即将与皇家钨冀进行一场足球友谊赛。与一般的足球比赛11人制不同,这场友谊赛两队各有n位球员同时在场上奔跑,场面十分壮(hun)观(luan)。当然,球还是只有一个。

          现在,FC幽寂主教练卡犇要制定战术。在进攻上,为了保证团队的协调有序,(直接)传球必须在特定球员之间进行,方向不限。例如门将只会与最近的几个后卫传球。

    受到个人能力和球员间默契的影响,可直接传球的两个球员之间有一个特定的失误系数,越大则表示越容易失误。不可直接传球的两个球员之间想要进行球的传递,则需通过其他球员来间接传球(战术已保证一个球员能直接或间接传给其他任意球员)。可直接传球球员之间也可以间接传球。根据木桶原理,间接传球的失误系数等于传球路线中所有直接传球的最大的失误系数。

          在制定高级战术过程中,卡犇需要知道两名球员间传球(包括直接和间接)可能达到的最小的失误系数是多少。然而由于球员太多……

    【输入】

          输入文件名为friendly.in。

          第一行两个正整数n、m,分别表示FC幽寂队场上球员数和可直接传球的球员有多少对。

          接下来n行,每行一个字符串,分别表示每位球员姓名。

    接下来m行,每行两个字符串s1、s2和一个正整数k,之间用一空格隔开,表示名为s1和名为s2的两个球员可以直接传球,失误系数为k。

          第n+m+2行一个正整数q,表示卡犇的询问数。

          接下来q行,每行两个字符串s1、s2,表示卡犇想知道名为s1和名为s2的两个球员之间传球可达的最小失误系数。

          数据没有多余的空格和回车。

    【输出】

          输出文件名为friendly.out。

          共q行,每行一个正整数,依次表示每个询问的答案。

    【输入输出样例1】          【输入输出样例2】

    friendly.in

    friendly.in

    6 8

    KCN

    COS

    HOCN

    CH4

    HCOOH

    CH3COOH

    KCN COS 2

    KCN HOCN 1

    COS HOCN 4

    COS CH4 5

    HOCN HCOOH 3

    CH4 HCOOH 2

    CH4 CH3COOH 2

    CH3COOH HCOOH 1

    2

    KCN CH3COOH

    COS CH4

    11 21

    Neuer

    LiYi

    JJRoger

    Xujiale

    Shaqima

    Gundogan

    CRonaldo

    Naldo

    Mkhitaryan

    Messi

    GoalKeeper

    Neuer LiYi 101

    Neuer Xujiale 4

    Neuer JJRoger 7

    LiYi JJRoger 100

    LiYi Shaqima 99

    JJRoger Xujiale 10

    JJRoger Shaqima 11

    JJRoger Gundogan 6

    Xujiale Gundogan 3

    Xujiale CRonaldo 8

    Xujiale Naldo 5

    Gundogan Shaqima 10

    Gundogan Naldo 6

    Gundogan Mkhitaryan 9

    Shaqima Mkhitaryan 21

    Shaqima Messi 20

    Naldo Mkhitaryan 10

    Naldo GoalKeeper 9

    Mkhitaryan GoalKeeper 9

    CRonaldo Naldo 1

    Messi Mkhitaryan 1

    4

    LiYi GoalKeeper

    CRonaldo Messi

    JJRoger Shaqima

    Neuer GoalKeeper

    friendly.out

    friendly.out

    3

    3

    99

    9

    10

    9

    【数据范围】

          对于10%的数据,n≤100,m≤1,000,q≤100;

          对于30%的数据,n≤1,000,m≤1,000,q≤1,000;

          对于60%的数据,n≤1,000,m≤100,000,q≤100,000;

          对于100%的数据,n≤100,000,m≤100,000,q≤100,000,失误系数≤100,000,000,球员名字互不相同且长度不超过10个字符。

    不得不说,这道题有些丧病。。。考试时想了许久,最后暴力只过了20分QAQ。正解也是相当繁杂,先用kruskal来算最小生成树,之后用倍增求出两点到他们最近公共祖先的路径长度,取二者较大值即为答案。下面贴出代码(长的没有底哦):

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <map>
    #include <string>
    #include <algorithm>
    using namespace std;
    FILE *fin=fopen("friendly.in","r"),*fout=fopen("friendly.out","w");
    long n,m,qn;
    struct pat{long x,y,s;} a[100005];
    bool operator <(pat a,pat b){
        return a.s<b.s;
    }
    long mb,mc,bh[100005],h[100005];
    struct pat2{long lh,to,s,h;} b[200005];
    void newb(long x,long y,long s){
        mb++; b[mb].to=y; b[mb].s=s; b[mb].lh=bh[x]; bh[x]=mb;
        mb++; b[mb].to=x; b[mb].s=s; b[mb].lh=bh[y]; bh[y]=mb;
    }
    map<string,long> M;
    struct xxx{long s,h;} d[100005][20];
    struct UFS{
        long n,fa[1000005];
        void init(long nn){
            n=nn;
            for (long i=0;i<nn;i++) fa[i]=i;
        }
        long root(long p){
            if (fa[p]!=p) fa[p]=root(fa[p]);
            return fa[p];
        }
        void uni(long x,long y){
            fa[root(x)]=root(y);
        }
    }U;
    inline void rut(string &s,char cc){
        char c;
        s="";
        for(fscanf(fin,"%c",&c);c!=cc&&!feof(fin);fscanf(fin,"%c",&c)) s+=c;
    }
    void init(){
        long i;
        string s;
        fscanf(fin,"%ld%ld
    ",&n,&m);
        M.clear();
        for (i=0;i<n;i++){
            rut(s,'
    ');
            M[s]=i;
            //cout<<s<<endl;
        }
        for (i=0;i<m;i++){
            rut(s,' '); a[i].x=M[s]; //cout<<s<<endl;
            rut(s,' '); a[i].y=M[s]; //cout<<s<<endl;
            fscanf(fin,"%ld
    ",&(a[i].s)); //cout<<a[i].s<<endl;
            //cout<<a[i].x<<' '<<a[i].y<<' '<<a[i].s<<endl;
        }
        mb=0;
        for (i=0;i<n;i++) bh[i]=0;
    }
    void Kruskal(){
        sort(a,a+m);
        U.init(n);
        for (long i=0;i<m;i++)
            if (U.root(a[i].x)!=U.root(a[i].y)){
                U.uni(a[i].x,a[i].y);
                newb(a[i].x,a[i].y,a[i].s);
                cout<<a[i].x<<' '<<a[i].y<<' '<<a[i].s<<endl;
            }
    }
    void dinit(){
        long i,t,k,p=0,q=1,Q[100005],P;
        bool f[100005];
        memset(f,0,sizeof(f));
        d[0][0].s=0; d[0][0].h=-1;
        h[0]=0; f[0]=1; Q[0]=0;
        while (p<q){
            P=Q[p];
            for (i=bh[P];i>0;i=b[i].lh){
                t=b[i].to;
                if (!f[t]){
                    f[t]=1;
                    Q[q++]=t;
                    d[t][0].s=b[i].s;
                    d[t][0].h=P;
                    h[t]=h[P]+1;
                }
            }
            p++;
        }
        for (k=1;k<20;k++)
            for (i=0;i<n;i++){
                t=d[i][k-1].h;
                if (t>-1){
                    d[i][k].h=d[t][k-1].h;
                    d[i][k].s=max(d[i][k-1].s,d[t][k-1].s);
                }else d[i][k].h=-1;
            }
    }
    void tr(){
        long i,j,k,p,q,pp,qq,ans;
        string s;
        fscanf(fin,"%ld
    ",&qn);
        for (i=0;i<qn;i++){
            rut(s,' '); p=M[s]; //cout<<s<<endl;
            rut(s,'
    '); q=M[s]; //cout<<s<<endl;
            //cout<<p<<' '<<q<<endl;
            ans=0;
            if (h[p]<h[q]) {k=p;p=q;q=k;}
            for (j=0,k=h[p]-h[q];k>0;j++,k>>=1)
                if (k%2==1){
                    if (ans<d[p][j].s) ans=d[p][j].s;
                    p=d[p][j].h;
                }
            //cout<<h[p]<<' '<<h[q]<<endl;
            if (p==q){
                fprintf(fout,"%ld
    ",ans);
                continue;
            }
            pp=p; qq=q;
            for (j=19;j>=0;j--)
                if (d[pp][j].h>-1){
                    if (d[pp][j].h==d[qq][j].h)
                        k=d[pp][j].h;
                    else{
                        pp=d[pp][j].h;
                        qq=d[qq][j].h;
                    }
                }
            for (j=0,k=h[p]-h[k];k>0;j++,k>>=1)
                if (k%2==1){
                    if (ans<d[p][j].s) ans=d[p][j].s;
                    if (ans<d[q][j].s) ans=d[q][j].s;
                    p=d[p][j].h;
                    q=d[q][j].h;
                }
            fprintf(fout,"%ld
    ",ans);
        }
    }
    int main(){
        init();
        Kruskal();
        dinit();
        tr();
        fclose(fin);
        fclose(fout);
        return 0;
    }

    清清正正射命丸文是也~

  • 相关阅读:
    ASP.NET常用信息保持状态学习笔记二
    初识HTTP协议请求与响应报文
    Linux下基于C的简单终端聊天程序
    Linux基于CURSES库下的二维菜单
    aspx与ashx
    linux下基于GTK窗口编程
    ajaxjquery无刷新分页
    asp.net管道模型(管线模型)(内容转载至博客园)
    ASP.NET常用信息保持状态学习笔记一
    ASP.NET使用管道模型(PipleLines)处理HTTP请求 (内容出自CSDN)
  • 原文地址:https://www.cnblogs.com/Ayateriteri/p/5689710.html
Copyright © 2011-2022 走看看