hdu4324-Triangle LOVE-2012 Multi-University Training Contest题解

来源:互联网 发布:淘宝越来越难做了 编辑:程序博客网 时间:2024/05/22 15:56

Brief Description:

给定一个n*n的矩阵A,A[i][j]=1表示i喜欢j,A[i][j]=0表示i不喜欢j。规定A[i][i]=0且对任意i,j(i!=j)有A[i][j]=1或A[j][i]=1,且A[i][j]!=A[j][i],表示任意2个人一定存在喜欢关系,但是不能互相喜欢,即在有向图,保证任意两点间仅有一条有向边。现在若发现有i喜欢j,j喜欢k,k喜欢i(三角恋关系)则输出"Yes",否则输出"No"。


Analysis:
比赛时这题队友暴力过的,但是对于n=2000,O(n^2)的算法比较妥当。
下面介绍O(n^2)的解法:
首先从i从0到n-1依次枚举,当前枚举到i时,可以将之前的0到i-1划分为2个部分left和right,i喜欢left中的每一个人,right中的每一个人喜欢i,现在的关键是能否找到left中的k喜欢right中的某一个人p,这样就找到了i->k->p->i,满足条件。
我们可以统计left中点的入度和lin(把left中每个点的入度加起来),出度和lout,left中节点个数l,right中节点个数r,
若lin-lout=r*l,则此时不存在三角恋,否则存在三角恋。
具体看以下代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>using namespace std;const int maxn = 2005;char a[maxn][maxn];bool vis[maxn];int n;int main(){    int cas,ta=1;    scanf("%d",&cas);    while(cas--){        int i,j,lin,lout,l,r;        scanf("%d",&n);        for(i=0; i<n; i++) scanf(" %s",a[i]);        int in[maxn]={0},out[maxn]={0};        for(i=0; i<n; i++){           if(i < 2){              if(i == 1){                if(a[0][1] == '1') in[1]=1,out[0]=1;                else in[0]=1,out[1]=1;              }              continue;           }           l = lin = lout = 0;           for(j=0; j<i; j++) // 2012_9_13评注:i是三角恋中序号最大的              if(a[i][j] == '1'){                 l++; // left多1                 lin += in[j];  lout += out[j];  out[i]++;   in[j]++;              }else{                 out[j]++;   in[i]++;              }           r = i - l;           if(lin-lout != r*l) break;        }        printf("Case #%d: ",ta++);        if(i < n) puts("Yes");        else puts("No");    }    return 0;}


原创粉丝点击