poj 3660 弗洛伊德算法的巧妙改变。

来源:互联网 发布:国外语音聊天软件 编辑:程序博客网 时间:2024/06/05 14:37

题目就是说一群牛比谁更厉害,进行了几局较量,每一局都有胜负,能够知道谁能战胜谁,若A打败B,B打败C,则A就能打败C,具有传递性。

最终输出的是能够排名的牛的个数。

若这头牛打过了x只牛,被y只牛打败,而且x+y==n-1,则这个牛就能排名,对吧?(因为这头牛不管和谁打,结果我们知道。)

这里mp数组变化了意义,但是重要思路还是弗洛伊德的算法。

算是弗洛伊德的变式吧,这个问题其实也不是最短路问题,只不过用了一个最短路的算法解决了一个不是最短路的问题。

mp[i][j]==true的意义是i能打过j。

由于只有 两个选择,要么打过,要么被打过,所以我用bool对这个图进行了储存。(代码中我用了relationship作为数组的名称。)

显然如果mp[i][k]&&mp[k][j],则mp[i][j]=true.

flody过后,你要统计一下这个牛的确定的次数够不够n-1(n是牛的总数)。如不够,就不能排名;若够,就能排名。

注意统计的时候mp[i][j]算一次,mp[j][i]同样也要算一次。

个人水平有限,可以看看其他牛犇的博客看看他们的解释。

AC代码:


#include <iostream>#include <string>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int maxn=1e2+5;const int inf=0x3f3f3f3f;bool relationship[maxn][maxn];int N,M;void floyd(){    for(int k=1;k<=N;k++)        for(int i=1;i<=N;i++)            for(int j=1;j<=N;j++)                if(relationship[i][k]&&relationship[k][j])                    relationship[i][j]=1;    return;}int main(){    while(scanf("%d%d",&N,&M)==2)    {        memset(relationship,0,sizeof(relationship));        int t1,t2;        for(int i=0;i<M;i++)        {            scanf("%d%d",&t1,&t2);            relationship[t1][t2]=1;        }        floyd();        int ans=0;        for(int i=1;i<=N;i++)        {            int settled=0;            for(int j=1;j<=N;j++)            {                if(relationship[i][j]||relationship[j][i])                    settled++;            }            if(settled==N-1)                ans++;        }        printf("%d\n",ans);    }}

原创粉丝点击