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