HDOJ 4324 —— 拓扑排序 || DFS时间戳 || 竞赛图

Triangle LOVE

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1904    Accepted Submission(s): 812

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). A
i,j = 1 means i-th people loves j-th people, otherwise A
i,j = 0.

It is guaranteed that the given relationship is a tournament, that is, A
i,i= 0, A
i,j ≠ A
j,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  

Author BJTU  

Source
2012 Multi-University Training Contest 3  

Recommend zhoujiaqi2010  
两种方法:
第一种是DFS去记录时间戳,找到时间戳差2的环。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>

using namespace std;
//#define Online_Judge
#define outstars cout << "***********************" << endl;
#define clr(a,b) memset(a,b,sizeof(a))
#define lson l , mid  , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
//#define mid ((l + r) >> 1)
#define mk make_pair
#define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++)
#define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++)
#define REP(i , x , n) for(int i = (x) ; i > (n) ; i--)
#define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--)
const int MAXN = 2000 + 50;
const long long LLMAX = 0x7fffffffffffffffLL;
const long long LLMIN = 0x8000000000000000LL;
const int INF = 0x7fffffff;
const int IMIN = 0x80000000;
#define eps 1e-8
#define mod 1000000007
typedef long long LL;
const double PI = acos(-1.0);
typedef double D;
typedef pair<int , int> pi;
///#pragma comment(linker, "/STACK:102400000,102400000")
int a[MAXN][MAXN] , dfn[MAXN];
int n;
int maxnum;
char str[MAXN];
int dfs(int u , int t)
{
    dfn[u] = t;
    maxnum = max(maxnum , t);
    int cnt = 0;
    FOR(i , 0 , n)
    {
        if(a[u][i])
        {
            if(!dfn[i])cnt |= dfs(i , t + 1);
            else if(dfn[i] + 2 == t)return 1;
        }
    }
    return cnt;
}
int solve()
{
    FOR(i , 0 , n)
    {
        if(!dfn[i]&&dfs(i, maxnum + 1))return 1;
    }
    return 0;
}
int main()
{
    //ios::sync_with_stdio(false);
    #ifdef Online_Judge
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif // Online_Judge
    int t;
    cin >> t;
    FORR(kase , 1 , t)
    {
        maxnum = 0;
        scanf("%d" , &n);
        clr(dfn , 0);
        printf("Case #%d: " , kase);
        FOR(i , 0 , n)
        {
            scanf("%s" , str);
            FOR(j , 0 , n)
            {
                a[i][j] = str[j] - '0';
            }
        }
        if(solve())puts("Yes");
        else puts("No");
    }
    return 0;
}

第二种是计算是否存在拓扑序,因为有环的话是不存在拓扑序的,而且本题中只要有环就是三元环。

#include <iostream> #include <cstdio> #include <cstring> using namespace std; char map[2010][2010]; int v[2010]; int main() { int N,t; while(scanf("%d",&N)!=EOF) { getchar(); for(int ti=0;ti<N;ti++) { scanf("%d",&t); getchar(); memset(v,0,sizeof(v)); for(int i=0;i<t;i++) { for(int j=0;j<t;j++) { map[i][j]=getchar(); if(map[i][j]=='1') v[j]++; } getchar(); } int p=0,state=0; for(int i=0;i<t;i++) { p=0; while(v[p]!=0) p++; if(p>=t) { state=1; break; } else { v[p]--; for(int j=0;j<t;j++) { if(map[p][j]=='1') v[j]--; } } } if(state==1) printf("Case #%d: Yes\n",ti+1); else printf("Case #%d: No\n",ti+1); } } return 0; }


第三种,没看懂,详见http://www.haogongju.net/art/1572613

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/acm_xmzhou/article/details/12317767
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞