思路就是简单的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");
	}
}