D112 最短路→传递闭包 Floyd 算法 P1347 排序

D112 最短路→传递闭包 Floyd 算法 P1347 排序_哔哩哔哩_bilibili

 

P1347 排序 - 洛谷

给 m 个小于关系,判断字母之间的关系:若矛盾,输出发生位置;若不确定,输出不确定;若确定,输出顺序

思路

枚举 m 个小于关系,每次做 Floyd 求传递关系,$d[i][j]=1$ 表示 $i<j$,然后进行检查:

1. 如果 $d[i][i]=1$,那么就是出现了环,发现矛盾,返回 opt = 1

2. 如果 $d[i][j]=d[j][i]=0$,那么说明 $i、j$ 两个点之间的关系不确定,返回 opt = 0

3. 异常情况都排除了,说明 n 个点的大小关系确定,返回 opt = 2

image

相关板子:

D111【模板】最短路→传递闭包 Floyd 算法 B3611 传递闭包 - 董晓 - 博客园

 

// 传递闭包 Floyd 算法 O(m*n^3)
#include<bits/stdc++.h>
using namespace std;

const int N=30;
int n,m;
int d[N][N],vis[N];

void floyd(){
  for(int k=0; k<n; k++)
  for(int i=0; i<n; i++)
  for(int j=0; j<n; j++)
    d[i][j]|=d[i][k]&d[k][j]; //d[i,j]=1 表示 i<j
}
int check(){
  for(int i=0; i<n; i++)if(d[i][i]) return 1; //发现矛盾
  for(int i=0; i<n; i++)
  for(int j=0; j<i; j++)
    if(!d[i][j] && !d[j][i]) return 0; //关系不确定
  return 2; //关系确定
}
char get(){
  for(int i=0; i<n; i++)if(!vis[i]){ //若i未输出
    bool flag=true;
    for(int j=0; j<n; j++)if(!vis[j] && d[j][i]){ //j未输出且j<i,则不合法
      flag=false; break;
    }
    if(flag){vis[i]=true; return 'A'+i;}
  }
}
int main(){
  cin>>n>>m;
  int opt=0,pos;
  for(int i=1; i<=m; i++){
    char a,b,c; cin>>a>>b>>c;
    if(opt==0){ //若关系不确定
      d[a-'A'][c-'A']=1;
      floyd();  //Floyd求传递关系
      opt=check();
      pos=i;    //记录当前关系位次
    }
  }
  if(opt==0)puts("Sorted sequence cannot be determined.");
  if(opt==1)printf("Inconsistency found after %d relations.\n",pos);
  if(opt==2){
    printf("Sorted sequence determined after %d relations: ",pos);
    for(int i=0; i<n; i++) printf("%c",get());
    printf(".\n");
  }
}

 

// 传递闭包 拓扑排序
#include<bits/stdc++.h>
using namespace std;

const int N=30;
int n,m,pre[N];
vector<int> e[N];
bool g[N][N];

int bfs(int k){
  int d[N]={0};d[0]=1;
  queue<int> q;
  q.push(0);
  while(q.size()){
    int u=q.front(); q.pop();
    for(int v:e[u]){
      if(d[v]<d[u]+1){
        d[v]=d[u]+1;
        pre[n+1]=v; pre[v]=u; //记录前驱
        q.push(v);
      }
      if(d[v]>n+2) return 1; //发现矛盾
    }
  }
  if(d[n+1]==n+2) return 2; //关系确定
  return 0; //关系不确定
}
void dfs(int v){
  if(pre[v]) dfs(pre[v]);
  cout<<char('A'+v-1); //输出
}
int main(){
  cin>>n>>m;
  for(int i=1; i<=n; i++)
    e[0].push_back(i), e[i].push_back(n+1); //虚拟源点、汇点
  int opt=0,p;
  for(int i=1; i<=m; i++){
    char a,b,c; cin>>a>>b>>c;
    if(opt==0){ //若关系不确定
      int u=a-'A'+1, v=c-'A'+1;
      if(!g[u][v]) e[u].push_back(v), g[u][v]=1; //去重边
      opt=bfs(i);
      p=i; //记录当前关系位次
    }
  }
  if(opt==0) puts("Sorted sequence cannot be determined.");
  if(opt==1) printf("Inconsistency found after %d relations.",p);
  if(opt==2){
    printf("Sorted sequence determined after %d relations: ",p);
    dfs(pre[n+1]); printf(".");
  }  
}

 

posted @ 2026-03-24 18:52  董晓  阅读(88)  评论(0)    收藏  举报