1. 程式人生 > >藍書(演算法競賽進階指南)刷題記錄——POJ1094 Sorting It All Out(floyd)

藍書(演算法競賽進階指南)刷題記錄——POJ1094 Sorting It All Out(floyd)

題目: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;
}