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
 

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值