拓扑排序 hdu4324 Triangle LOVE

传送门:点击打开链接

题意:每两个点之间必有且仅有一条有向边,问是否存在一个3元环。

思路:这题与普通的求环有2个不一样的地方,一个是每两个点必有一条边,一个是只是求3元环而已。。然而我们可以证明,如果每两个点之间必有一条边存在环,那么必然会存在3元环。假设某一个n元环上存在a->b->c->d这样的4个,如果d就是a,那么(a,b,c)就直接构成了3元环之间满足题意。如果d不是a,那么就必有a->c,那么又形成了a->c->d,也就是说,n元环退化到n-1元环。以此可以继续递推下去,最后可以证明出,只要存在环,那么必有3元环~

不得不吐槽一句,刚开始一直用getchar一直超时,一改成scanf用%s就过了- -

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck printf("fuck")
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;

const int MX = 2000 + 5;

int IN[MX];
char G[MX][MX];

int main() {
    int T, n, ansk = 0; //FIN;
    scanf("%d", &T);
    while(T--) {
        memset(IN, 0, sizeof(IN));
        scanf("%d", &n);

        for(int i = 1; i <= n; i++) {
            scanf("%s", G[i] + 1);
            for(int j = 1; j <= n; j++) {
                if(G[i][j] == '1') IN[j]++;
            }
        }

        queue<int>Q;
        for(int i = 1; i <= n; i++) {
            if(!IN[i]) Q.push(i);
        }

        int ans = 0;
        while(!Q.empty()) {
            int u = Q.front();
            Q.pop();
            ans++;

            for(int v = 1; v <= n; v++) {
                if(G[u][v]) {
                    IN[v]--;
                    if(!IN[v]) Q.push(v);
                }
            }
        }

        printf("Case #%d: %s\n", ++ansk, ans == n ? "No" : "Yes");
    }
    return 0;
}


你可能感兴趣的:(拓扑排序 hdu4324 Triangle LOVE)