蓝书(算法竞赛进阶指南)刷题记录——POJ1094 Sorting It All Out(floyd)

版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/82995888

题目:POJ1094.

题目大意:给定n组不等关系,格式为x<y.现在要求输出最早能够确定唯一顺序或产生矛盾的位置,或输出没有这样一个位置,若有唯一顺序要输出顺序.

注意这道题的输出格式.

这道题一看想到了差分约束,仔细一想用floyd跑差分约束,然后发现好像确实可做.

我们用设f[i][j]为true表示i<j,那么我们可以将所有关系转化,然后就可以跑一遍Floyd,接下来若有一对x,y满足f[x][y]=f[y][x]=true,就说明矛盾,否则说明不矛盾.

要求出第几对之后矛盾,我们可以二分求解,或者也可以暴力枚举在第几对之后.

若不矛盾,我们要确定唯一顺序的话,我们可以发现若有唯一顺序的话,那么肯定满足一对x,y不存在f[x][y]=f[y][x]=false的情况.

求出唯一顺序可以使用暴力枚举每一个点,也可以直接使用拓扑排序求解.

至于求解在第几对之后,二分一下就好,当然也可以暴力枚举.

我这道题一开始以为它是要先判断所有边是否有矛盾或有唯一顺序,但是题目是要边读入边判.

代码如下:

//#include<bits/stdc++.h>
#include<iostream>
  using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=26,M=N*N;
struct side{
  int x,y;
}e[M+9];
int n,m;
int flag,ans,pre[N+9];
int f[N+9][N+9];
void floyd(int mid){
  if (mid>m) mid=m;
  for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
      f[i][j]=0;
  for (int i=1;i<=mid;i++)
    f[e[i].x][e[i].y]=1;
  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];
}
bool check_con(int mid){
  if (mid>m) mid=m;
  floyd(mid);
  for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
      if (i^j&&f[i][j]&f[j][i]) return true;
  return false;
}
bool check_order(int mid){
  if (mid>m) mid=m;
  floyd(mid);
  for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
      if (i^j&&!(f[i][j]^f[j][i])) return false;
  return true;
}
char rc(){
  char c=getchar();
  while (c<'A'||c>'Z') c=getchar();
  return c; 
}
Abigail into(){
  char c1,c2;
  for (int i=1;i<=m;i++){
    c1=rc();c2=rc();
    e[i].x=c1-'A'+1;e[i].y=c2-'A'+1;
  }
}
Abigail work(){
  flag=2;
  for (int i=1;i<=m;i++){
    if (check_con(i)) flag=0;
    if (check_order(i)) flag=1;
    ans=i;
    if (flag^2) break;
  }
}
Abigail outo(){
  switch (flag){
    case 0:printf("Inconsistency found after %d relations.\n",ans);
           break;
    case 1:printf("Sorted sequence determined after %d relations: ",ans);
           floyd(ans);
           for (int i=1;i<=n;i++)
             pre[i]=0;      //查了一个下午错发现自己没有初始化pre为0...
           for (int i=1;i<=n;i++)
             for (int j=1;j<=m;j++)
               if (f[i][j]&&i^j) pre[j]++;
           for (int i=0;i<n;i++)
             for (int j=1;j<=n;j++)
               if (pre[j]==i) putchar(j-1+'A');
           putchar('.');putchar('\n');
           break;
    case 2:printf("Sorted sequence cannot be determined.\n");
           break;
  }
}
int main(){
  while (~scanf("%d%d",&n,&m)&&n){
    into();
    work();
    outo();
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/82995888