2010-1063

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

题目的意思是,有n个人要进行比赛,现在已经比了m场胜负关系已知的比赛,其中胜负关系是具有传递性的,就是说,如果A胜B,B胜C,那么如果有A和C的比赛,一定是A胜C,否则这个记录就是错的。

接下来还有P场没有记录的比赛,其中比赛的结果要用已经知道的m场的胜负关系推断出来,如果任何一场不能判断,就输出"Can't judge."

这题的做法就是把胜负关系看成有向图的边,读进来m条边之后,先判断是有存在圈。然后在计算每一个点对的连通性。最后对读进来的p场比赛的结果进行判断和统计。

代码:


{{{
#!cpp
#include <cstdio>
#include <cstring>
#include <map>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;


const int maxn=1100;
vector<int> E[maxn];
int v[maxn];
int score[maxn];
int d[maxn];
int g[maxn][maxn];
int gg[maxn][maxn];
int w[maxn];


int main(){
    int t =0;
    int n,m;
    while ( scanf("%d%d",&n,&m)!=EOF ) {
        if ( t ) printf("\n");
        ++t;
        memset(d,0,sizeof(d));      
        map<string,int> id;
        vector<string> ans;
        vector<string> name;
        memset(w,0,sizeof(w));
        for(int i=0;i<maxn;++i)E[i].clear();
        int cnt=0;
        memset(g,0,sizeof(g));
        for(int i=0;i<m;++i){
            char s1[20],s2[20];
            scanf("%s%s",s1,s2);
            int &a = id[string(s1)];
            int &b = id[string(s2)];
            if ( a == 0 ) {
                a = ++cnt;
                name.push_back(string (s1));
            }

            if ( b == 0 ) {
                b = ++cnt;
                name.push_back(string (s2));
            }
            char result[100];
            scanf("%s",result);
            if ( *result == 'w' ) {
                E[a].push_back(b);
                ++d[b];
                g[a][b] = 1; 
                ++w[a];
            }
            else {
                ++w[b];
                E[b].push_back(a);
                ++d[a];
                g[b][a] =1 ;
            }
        }

        memset(v,0,sizeof( v));
        int flag = 1 ; 
        int l[maxn];
        for(int i=0;i<n && flag;++i){
            int k; 
            flag = 0 ;
            for(int j=1;j<=n;++j) if ( !v[j] && d[j] == 0 )  {
                k = j ;
                flag= 1;
                break;
            }
            if ( !flag ) break;
            v[k]=1;
            for(int j=0;j<E[k].size();++j){
                d[E[k][j]] -- ;
            }
            l[i]=k;
        }


        if ( flag ) {
            memset(gg,0,sizeof(gg));        
            for(int i=n-1;i>=0;--i){
                for(int j=i+1;j<n;++j)if ( g[l[i]][l[j]]) {
                    gg[l[i]][l[j]] = 1; 
                    for(int k=j+1;k<n;++k) if ( gg[l[j]][l[k]] ) {
                        gg[l[i]][l[k]]= 1; 
                    }

                }
            }



            int p ;
            scanf("%d" , &p ) ; 
            while ( p -- ) {
                char s1[20] , s2[20]; 
                scanf("%s%s",s1,s2);
                int &a = id[string(s1)];
                int &b = id[string(s2)];
                if ( gg[a][b] ) {
                    w[a] ++ ; 
                }
                else if ( gg[b][a] ) {
                    w[b] ++ ; 
                }
                else {
                    flag = 0 ;
                }
            }
            if ( !flag ) {
                printf("Can't judge.\n");
            }
            else {

                int tmp=0;
                for(int i=1;i<=n;++i){
                    if ( w[i] > tmp ) tmp = w[i]; 
                }
                for(int i=1;i<=n;++i){
                    if (w[i]==tmp ) {
                        ans.push_back(name[i-1]);
                    }
                }
                sort(ans.begin(),ans.end());
                for(int i=0;i<ans.size();++i){
                    printf("%s\n" ,ans[i].c_str());
                }
            }
        }
        else {
            int p ; 
            scanf("%d", &p ) ; 
            while ( p -- ) {
                char s1[20] , s2[20 ] ;
                scanf("%s%s", s1 , s2 ) ; 
            }
            printf("Stupid Hiroshi.\n");
        }

    }
    return 0;
}


}}}

题目的意思是,有n个人要进行比赛,现在已经比了m场胜负关系已知的比赛,其中胜负关系是具有传递性的,就是说,如果A胜B,B胜C,那么如果有A和C的比赛,一定是A胜C,否则这个记录就是错的。

接下来还有P场没有记录的比赛,其中比赛的结果要用已经知道的m场的胜负关系推断出来,如果任何一场不能判断,就输出"Can't judge."

这题的做法就是把胜负关系看成有向图的边,读进来m条边之后,先判断是有存在圈。然后在计算每一个点对的连通性。最后对读进来的p场比赛的结果进行判断和统计。

代码:

#include <cstdio>
#include <cstring>
#include <map>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=1100;
vector<int> E[maxn];
int v[maxn];
int score[maxn];
int d[maxn];
int g[maxn][maxn];
int gg[maxn][maxn];
int w[maxn];
int main(){
    int t =0;
    int n,m;
    while ( scanf("%d%d",&n,&m)!=EOF ) {
        if ( t ) printf("\n");
        ++t;
        memset(d,0,sizeof(d));      
        map<string,int> id;
        vector<string> ans;
        vector<string> name;
        memset(w,0,sizeof(w));
        for(int i=0;i<maxn;++i)E[i].clear();
        int cnt=0;
        memset(g,0,sizeof(g));
        for(int i=0;i<m;++i){
            char s1[20],s2[20];
            scanf("%s%s",s1,s2);
            int &a = id[string(s1)];
            int &b = id[string(s2)];
            if ( a == 0 ) {
                a = ++cnt;
                name.push_back(string (s1));
            }
            if ( b == 0 ) {
                b = ++cnt;
                name.push_back(string (s2));
            }
            char result[100];
            scanf("%s",result);
            if ( *result == 'w' ) {
                E[a].push_back(b);
                ++d[b];
                g[a][b] = 1; 
                ++w[a];
            }
            else {
                ++w[b];
                E[b].push_back(a);
                ++d[a];
                g[b][a] =1 ;
            }
        }
        memset(v,0,sizeof( v));
        int flag = 1 ; 
        int l[maxn];
        for(int i=0;i<n && flag;++i){
            int k; 
            flag = 0 ;
            for(int j=1;j<=n;++j) if ( !v[j] && d[j] == 0 )  {
                k = j ;
                flag= 1;
                break;
            }
            if ( !flag ) break;
            v[k]=1;
            for(int j=0;j<E[k].size();++j){
                d[E[k][j]] -- ;
            }
            l[i]=k;
        }
        if ( flag ) {
            memset(gg,0,sizeof(gg));        
            for(int i=n-1;i>=0;--i){
                for(int j=i+1;j<n;++j)if ( g[l[i]][l[j]]) {
                    gg[l[i]][l[j]] = 1; 
                    for(int k=j+1;k<n;++k) if ( gg[l[j]][l[k]] ) {
                        gg[l[i]][l[k]]= 1; 
                    }
                }
            }
            int p ;
            scanf("%d" , &p ) ; 
            while ( p -- ) {
                char s1[20] , s2[20]; 
                scanf("%s%s",s1,s2);
                int &a = id[string(s1)];
                int &b = id[string(s2)];
                if ( gg[a][b] ) {
                    w[a] ++ ; 
                }
                else if ( gg[b][a] ) {
                    w[b] ++ ; 
                }
                else {
                    flag = 0 ;
                }
            }
            if ( !flag ) {
                printf("Can't judge.\n");
            }
            else {
                int tmp=0;
                for(int i=1;i<=n;++i){
                    if ( w[i] > tmp ) tmp = w[i]; 
                }
                for(int i=1;i<=n;++i){
                    if (w[i]==tmp ) {
                        ans.push_back(name[i-1]);
                    }
                }
                sort(ans.begin(),ans.end());
                for(int i=0;i<ans.size();++i){
                    printf("%s\n" ,ans[i].c_str());
                }
            }
        }
        else {
            int p ; 
            scanf("%d", &p ) ; 
            while ( p -- ) {
                char s1[20] , s2[20 ] ;
                scanf("%s%s", s1 , s2 ) ; 
            }
            printf("Stupid Hiroshi.\n");
        }
    }
    return 0;
}