题目:POJ1094.
题目大意:给定
26
26
26个字母的
n
n
n组不等关系,格式为
x
<
y
x<y
x<y.现在要求输出最早能够确定唯一顺序或产生矛盾的位置,或输出没有这样一个位置,若有唯一顺序要输出顺序.
注意这道题的输出格式.
这道题一看想到了差分约束,仔细一想用floyd跑差分约束,然后发现好像确实可做.
我们用设 f [ i ] [ j ] f[i][j] f[i][j]为 t r u e true true表示 i < j i<j i<j,那么我们可以将所有关系转化,然后就可以跑一遍Floyd,接下来若有一对 x , y x,y x,y满足 f [ x ] [ y ] = f [ y ] [ x ] = t r u e f[x][y]=f[y][x]=true f[x][y]=f[y][x]=true,就说明矛盾,否则说明不矛盾.
要求出第几对之后矛盾,我们可以二分求解,或者也可以暴力枚举在第几对之后.
若不矛盾,我们要确定唯一顺序的话,我们可以发现若有唯一顺序的话,那么肯定满足一对 x , y x,y x,y不存在 f [ x ] [ y ] = f [ y ] [ x ] = f a l s e f[x][y]=f[y][x]=false 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;
}