思路就是简单的dfs+标号, 若发现一趟dfs中又标号差2的, 则存在三角关系.
但写了N久还是wa....
有一个地方我觉得是有问题的, 就是在判断标号差2的时候, 有可能v的标号是前一趟dfs的而不是当前趟dfs的,
所以v的标号就不能说明什么问题了...这样可能导致wa
简言之就是要在判断的时候保证选的v都是当前趟dfs标号的.
看了 http://blog.ac521.org/?p=502&cpage=1#comment-181 的题解,
比对了后发现我是 标号差2写成了判断绝对值, 而他就是默认当前是较大的(这样没错, 但是不能解决我上面说的那个问题, 也就是说题目数据不完备, 能wa掉我, 不能wa掉他...?)
下面这代码是保证标号始终递增的, 从而解决了上述问题.
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
using namespace std;
int Rint() { int x; scanf("%d", &x); return x; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
#define bug(s) cout<<#s<<"="<<s<<" "
#define MAXN 2002
int G[MAXN][MAXN];
int dfn[MAXN]; //标号
int n;
int abs(int x) { return x<0? -x: x; }
int idx; //当前最大标号
int dfs(int u, int t)
{
dfn[u] = t;
idx = max(idx, t);
int ret = 0;
for(int i=0; i<n; i++) if(G[u][i])
{
if(!dfn[i])
{
ret |= dfs(i, t+1);
}
else
{
if(dfn[i] + 2==t) //若 i 是上一个连通快的, 则 dfn[i]必然小于 t
return 1; //存在
}
}
return ret;
}
int solve()
{
REP(n)
{
if(!dfn[i])
{
if(dfs(i, idx+1)) //始终从当前最大标号+1开始标记
{
return 1; //cunzai
}
}
}
return 0;
}
int main()
{
int t = Rint();
FOR(T, 1, t)
{
idx = 0;
memset(dfn, 0,sizeof(dfn));
printf("Case #%d: ", T);
n = Rint();
FOR(i, 0, n-1)
{
char buf[MAXN];
scanf("%s", buf);
FOR(j, 0, n-1)
{
G[i][j] = buf[j]-'0';
}
}
if(solve())
printf("Yes\n");
else
printf("No\n");
}
}