1. 程式人生 > >Gym 101873D - Pants On Fire - [warshall演算法求傳遞閉包]

Gym 101873D - Pants On Fire - [warshall演算法求傳遞閉包]

題目連結:http://codeforces.com/gym/101873/problem/D

 

題意:

給出 $n$ 個事實,表述為 "XXX are worse than YYY"。再給出 $m$ 個某人說的話,也是表述為 "XXX are worse than YYY",對於每句話都要判斷是否正確:

如果正確,輸出 "Fact";如果錯誤,輸出 "Alternative Fact";如果無法判斷,輸出 "Pants on Fire"。

 

題解:

本題是求傳遞閉包。

關於傳遞閉包,例如有 $A=\{0,1,2\}$,基於 $A$ 的關係集合 $R=\{<0,0>,<1,0>,<2,2>,<1,2>,<2,1>\}$,

而 $R$ 的傳遞閉包 $t(R) = \{<0,0>,<1,0>,<2,2>,<2,1>,<1,2>,<1,1>,<2,0>\}$。

學過離散數學都知道,可以用warshall演算法求傳遞閉包:

  首先用鄰接矩陣 $A$ 表示關係。

  (1)置新矩陣 $A=M$;
  (2)令 $j=1$; 
  (3)對所有 $i$ 如果 $A[i,j] = 1$,則對 $k = 1,2,\cdots,n$,$A[i,k] = A[i,k] or A[j,k]$;
  (4)$j+=1$(i是行,j是列);
  (5)如果 $j \le n$,則轉到步驟(3),否則演算法結束。

for(int j=1;j<=tot;j++) {
    for(int i=1;i<=tot;i++) {
        if(!edge[i][j]) continue;
        for(int k=1;k<=tot;k++) {
            edge[i][k]|=edge[j][k];
        }
    }
}

觀察一下上述程式碼,可改成:

for(int j=1;j<=tot;j++) {
    for(int i=1;i<=tot;i++) {
        for(int k=1;k<=tot;k++) {
            edge[i][k]
|=edge[i][j]&edge[j][k]; } } }

然後你就會發現,warshall演算法和floyd演算法異曲同工,然後你就會發現floyd演算法全名是floyd-warshall演算法。(QWQ)

 

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=400+10;
int n,m;
int edge[maxn][maxn];
int tot;
map<string,int> mp;
int main()
{
    cin>>n>>m;
    tot=0;
    mp.clear();
    memset(edge,0,sizeof(edge));
    for(int i=1,u,v;i<=n;i++)
    {
        string s;
        cin>>s;
        if(mp.count(s)) u=mp[s];
        else u=mp[s]=++tot;
        cin>>s; cin>>s; cin>>s;
        cin>>s;
        if(mp.count(s)) v=mp[s];
        else v=mp[s]=++tot;
        edge[u][v]=1;
    }
    for(int j=1;j<=tot;j++) {
        for(int i=1;i<=tot;i++) {
            for(int k=1;k<=tot;k++) {
                edge[i][k]|=edge[i][j]&edge[j][k];
            }
        }
    }
    for(int i=1,u,v;i<=m;i++)
    {
        string s;
        cin>>s;
        u=mp[s];
        cin>>s; cin>>s; cin>>s;
        cin>>s;
        v=mp[s];
        if(edge[u][v]) printf("Fact\n");
        else if(edge[v][u]) printf("Alternative Fact\n");
        else printf("Pants on Fire\n");
    }
}