b_aw_排序 & 奶牛比赛(floyd传递闭包)

排序

给定m对不等时,从前往后遍历每对关系,每次遍历时判断:

  • 如果能够确定全部关系且无矛盾,则结束循环,输出确定的次序;
  • 如果发生矛盾,则结束循环,输出有矛盾;
  • 如果循环结束时没有发生上述两种情况,则输出无定解。

思路:只要没确定所有关系或没找到矛盾,则没输入一对数据,用floyd更新闭包

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=30;
int n,m,g[N][N],f[N][N],vis[N];
void floyd() {
    memcpy(f,g,sizeof g);
    for (int k=0; k<n; k++)
    for (int i=0; i<n; i++)
    for (int j=0; j<n; j++) {
        f[i][j]|=f[i][k]&&f[k][j];
    }
}
int get_type() {
    for (int i=0; i<n; i++) if (f[i][i]) return 2; //矛盾
    for (int i=0; i<n; i++)
    for (int j=0; j<i; j++) if (!f[i][j] && !f[j][i]) //无法确定关系
        return 0;
    return 1;   //可确定所有关系
}
char get() {
    for (int i=0; i<n; i++) if (!vis[i]) {
        bool valid=true;
        for (int j=0; j<n; j++) {
            if (!vis[j] && f[j][i]) { //如果有比i还要小的字母未输出,则证明i不是合法闭包中字母
                valid=false;
                break;
            }
        }
        if (valid) {
            vis[i]=1;
            return (char) ('A'+i);
        }
    }
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0);
    while (cin>>n>>m, n||m) {
        memset(f,0,sizeof f), memset(g,0,sizeof g);
        int type=0,cnt;
        for (int i=0; i<m; i++) {
            string s; cin>>s;
            int u=s[0]-'A', v=s[2]-'A';
            if (type==0) {
                g[u][v]=1; //u<v
                floyd(); //传递闭包
                type=get_type();
                if (type!=0) cnt=i+1;
            }
        }
        if (type==1) {
            memset(vis,false,sizeof vis);
            printf("Sorted sequence determined after %d relations: ", cnt);
            for (int i=0; i<n; i++) printf("%c",get()); printf(".\n");
        }else if (type==2) printf("Inconsistency found after %d relations.\n", cnt); 
         else              printf("Sorted sequence cannot be determined.\n");
    }
    return 0;
}

奶牛比赛

n头牛,且给出m对信息表示比赛结果a、b,表示a赢了b;求排名可以确定的奶牛的数目

思路:如果一个奶牛可以和其他奶牛确定关系,则说明该奶牛可确定排位

#include<bits/stdc++.h>
using namespace std;
const int N=4505;
int n,m,f[N][N]; //f[i][j]=1表示i和j的关系可以确定
void floyd() {
    for (int k=1; k<=n; k++)
    for (int i=1; i<=n; i++)
    for (int j=1; j<=n; j++) {
        f[i][j]|=f[i][k]&&f[k][j];
    }
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin>>n>>m;
    for (int i=0; i<m; i++) {
        int u,v; cin>>u>>v;
        f[u][v]=1;
    }
    floyd();
    int ans=0; 
    for (int i=1; i<=n; i++) {
        bool flag=true;
        for (int j=1; j<=n; j++) if (i!=j && (!f[j][i] && !f[i][j])) {
            flag=false;
            break;
        }
        if (flag) ans++;
    }
    cout<<ans;
    return 0;
}
posted @ 2020-10-31 15:32  童年の波鞋  阅读(77)  评论(0编辑  收藏  举报