题目链接 http://acm.hdu.edu.cn/viewerror.php?rid=27085135
Problem Description
Recently, scientists find that there is love between any of two people. For example, between A and B, if A don’t love B, then B must love A, vice versa. And there is no possibility that two people love each other, what a crazy world!
Now, scientists want to know whether or not there is a “Triangle Love” among N people. “Triangle Love” means that among any three people (A,B and C) , A loves B, B loves C and C loves A.
Your problem is writing a program to read the relationship among N people firstly, and return whether or not there is a “Triangle Love”.
Input
The first line contains a single integer t (1 <= t <= 15), the number of test cases.
For each case, the first line contains one integer N (0 < N <= 2000).
In the next N lines contain the adjacency matrix A of the relationship (without spaces). Ai,j = 1 means i-th people loves j-th people, otherwise Ai,j = 0.
It is guaranteed that the given relationship is a tournament, that is, Ai,i= 0, Ai,j ≠ Aj,i(1<=i, j<=n,i≠j).
Output
For each case, output the case number as shown and then print “Yes”, if there is a “Triangle Love” among these N people, otherwise print “No”.
Take the sample output for more details.
Sample Input
2 5 00100 10000 01001 11101 11000 5 01111 00000 01000 01100 01110
Sample Output
Case #1: Yes Case #2: No
题意:
任何两个人a和b,要么a爱b,要么b爱a,不存在两个人相爱或者都不爱对方。给定t组测试样例,每组给个n维方阵,方阵中, 方阵中i行j列(1开始算)为1表示i爱j。 判定是否存在三角恋,即a爱b,b爱c,c爱a。
题解:
这道题其实就是一个裸的拓扑排序,只是我太笨,在想环的时候忽略了任意两点间必有连接的条件,然后就没想到怎么做,看了别人的题解才恍然大悟。。。
这题就直接走一遍拓扑排序,用邻接表的形式建图,建图时记录每个点的入度。
建图完后,一个for循环遍历将所有入度为0的点入队列,然后while循环取队首元素,将于队首元素邻接的点入度都减1,同时判断减1后入度是否为0,若是则入队。 每次取队首时,用一个计数器+1记录节点个数,最后判断计数器是否等于n,不等于的话则存在环,否则无环。
这道题就是先拓扑判断是否存在n元环,n元环必定存在a->b->c-这样的连接情况,如果c->a,那么直接就形成三元环满足题意了,如果a->c,那就排除掉b点剩下一个n-1元环,这样一直迭代下去一定会形成三元环a->b->c->a。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#define MAXN 2010
using namespace std;
int n;
vector<int> vec[MAXN];
queue<int> q;
char ch[MAXN];
int degree[MAXN]; // 存度数
// 初始化
void Init() {
memset(degree,0,sizeof(degree));
while(!q.empty()) q.pop();
for(int i = 1;i <= n;i++) vec[i].clear();
}
// 拓扑排序判环
bool TopoLogical() {
for(int i = 1;i <= n;i++) {
if(degree[i] == 0) {
q.push(i);
}
}
int cnt = 0;// 拓扑排序的节点数
int top;
int size;
while(!q.empty()) {
top = q.front();
q.pop();
cnt++;
size = vec[top].size();
for(int i = 0;i < size;i++) {
degree[vec[top][i]]--;
if(degree[vec[top][i]] == 0) {
q.push(vec[top][i]);
}
}
}
if(cnt != n) {
// 有环
return true;
}
return false;
}
int main()
{
int t;
int Case = 1;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
Init();
int len;
for(int i = 1;i <= n;i++) {
scanf("%s",ch+1);
len = strlen(ch+1);
for(int j = 1;j <= len;j++) {
if(ch[j] == '1') {
vec[i].push_back(j);
degree[j]++;
}
}
}
bool flag = TopoLogical();// 有环标记
printf("Case #%d: ",Case++);
if(flag == true) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
}