题目大意
给出一个有向图,判断是否含环(非自环)。
拓扑排序思路
在拓扑排序的过程中,不断查找是否有入度为0的点并删除与之相关的路径与减少与之相关点的入度。当图中还存在点但是入度为0的点不存在了,则说明含有环。
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mem(a,n) memset(a,n,sizeof(a))
#define FRER() freopen("input.txt", "r", stdin)
#define FREW() freopen("output.txt", "r", stdin)
typedef long long LL;
using namespace std;
const int inf = 0x3f3f3f3f, maxn = 100 + 10;
int road[maxn][maxn];
int in[maxn];
void init()
{
mem(road,0);
mem(in,0);
}
int main()
{
// FRER();
int n,m;
int u,v;
while(scanf("%d%d",&n,&m)&&n){
init();
while(m--) {
scanf("%d%d",&u,&v);
if(!road[u][v]) {
road[u][v]=1;
in[v]++;
}
}
queue<int> q;
int cnt=0;
for(int i=0;i<n;i++){
if(in[i]==0) {
q.push(i);
cnt++;
}
}
bool flag = true;
while(!q.empty()) {
u=q.front(); q.pop();
int i;
for(i=0;i<n;i++){
if(road[u][i]) {
in[i]--;
road[u][i]=0;
if(in[i]==0)
{
q.push(i); cnt++;
}
}
}
if(cnt==n) {
printf("YES\n");
flag=false;
break;
}
}
if(flag) printf("NO\n");
}
return 0;
}
Floyd思路
通过Floyd更新任意两点之间连通情况,如果一个点与自己连通了则说明有环。
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mem(a,n) memset(a,n,sizeof(a))
#define FRER() freopen("input.txt", "r", stdin)
#define FREW() freopen("output.txt", "r", stdin)
typedef long long LL;
using namespace std;
const int inf = 0x3f3f3f3f, maxn = 100 + 10;
int road[maxn][maxn];
int main()
{
// FRER();
int n, m;
int u, v;
while(~scanf("%d%d",&n,&m) && n) {
mem(road,0);
while(m--) {
scanf("%d%d", &u,&v);
road[u][v]=1;
}
int flag=true;
for(int k=0;k<n;k++) {
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(road[i][k]==1&&road[k][j]==1) road[i][j]=1;
if(road[i][j]==road[j][i] && road[j][i]==1) {
flag=false;
goto End;
}
}
}
}
End:
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}