HDU5961 —— 传递【竞赛图】【判断传递闭包】

题意:

      给一个竞赛图,将图分成两部分,判断两部分的图是否符合传递闭包,a->b,b->c,则a->c

解法:

     判定 —— P图 && Q图无环,P图 && ~Q图无环。

     因为P图中必须无环,Q图中必须无环。

     并且P中 点A可到达点B ,则点A和点B中间有一条边,因此如果不符合题意的话,即A可到达B,但A和B之间没有连边。

     因此Q中 A和B 一定有一条边,因此 P图 && ~Q图中有环。

代码1:【对于图中环的判定】【1000ms以内】

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define rep(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
const int M = 2016*2016+100;
const int N = 2500;

struct Edge{
	int to,next;
}e[2][M];
int head[2][N],tot1,tot2,n,dg[2][N];
char s[N];

void init()
{
	tot1 = tot2 = 1;
	rep(i,1,n) head[0][i] = head[1][i] = 0;
	rep(i,1,n) dg[0][i] = dg[1][i] = 0;
}

void add(int x,int y,int idx)
{
	if(idx == 0){
		e[0][++tot1].to = y; e[0][tot1].next = head[0][x]; head[0][x] = tot1;
		dg[0][y]++;
	}
	else{
		e[1][++tot2].to = y; e[1][tot2].next = head[1][x]; head[1][x] = tot2;	
		dg[1][y]++;
	}
}

//拓扑排序判断有向图中有无环
int solve(int idx)
{
	queue<int> q;
	while(q.size()) q.pop();
	rep(i,1,n)
		if(!dg[idx][i]) q.push(i);
	int cnt = 0;
	while(q.size())
	{
		int x = q.front();
		q.pop();
		cnt++;
		for(int i = head[idx][x]; i ; i = e[idx][i].next)
		{
			int y = e[idx][i].to;
			dg[idx][y]--;
			if(dg[idx][y] == 0) q.push(y);
		}
	}
//	printf("cnt: %d\n",cnt);
	if(cnt == n) return 0;
	else return 1;
}

int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		init();
		scanf("%d",&n);
		rep(i,1,n)
		{
			scanf("%s",s+1);
			rep(j,1,n)
			{
				if(s[j] == 'P' || s[j] == 'Q')
					add(i,j,0);
				if(s[j] == 'P')
					add(i,j,1);
				else if(s[j] == 'Q')
					add(j,i,1);
			}
		}
	/*	for(int i = head[0][1]; i ; i = e[0][i].next){
			printf("i:%d 1->to: %d\n",i,e[0][i].to);
		}*/
		if(solve(0) || solve(1)) printf("N\n");
		else printf("T\n");
	}
	return 0;
}

代码2:直接bfs判断是否满足传递闭包性质【3000+ms】 

【如果bfs是用前向星存图则为5000+ms,用vector存图则为3000+ms,原因不详】

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <ctime>
#include <vector>
#define rep(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
const int M = 2016*2016+100;
const int N = 2500;
const int inf = -1;

vector<int> v1[N],v2[N];
int n,book[N],vis[N];
char s[N];

inline int gi()
{
  int date = 0,m = 1; char ch = 0;
  while(ch!='-'&&(ch<'0'||ch>'9'))ch = getchar();
  if(ch=='-'){m = -1; ch = getchar();}
  while(ch>='0' && ch<='9')
    {
      date = date*10+ch-'0';
      ch = getchar();
    }return date*m;
}

inline int solve1(int x)
{
	rep(i,0,n) book[i] = 0;
	for(int k = v1[x].size()-1; k >= 0; k--)
	{
		book[v1[x][k]] = 1;
	}
	queue<int> q;
	q.push(x);
	while(q.size())
	{
		int y = q.front();
		q.pop();
		for(int i = v1[y].size()-1; i >= 0; i--)
		{
			int h = v1[y][i];
			if(book[h] == 0){
				return 0;
			} 
			else if(book[h] < 2){
				book[h]++;
				q.push(h);
			}
		}
	}
	return 1;
}

inline int solve2(int x)
{
	rep(i,0,n) book[i] = 0;
	for(int k = v2[x].size()-1; k >= 0; k--)
	{
		book[v2[x][k]] = 1;
	}
	queue<int> q;
	q.push(x);
	while(q.size())
	{
		int y = q.front();
		q.pop();
		for(int i = v2[y].size()-1; i >= 0; i--)
		{
			int h = v2[y][i];
			if(book[h] == 0){
				return 0;
			} 
			else if(book[h] < 2){
				book[h]++;
				q.push(h);
			}
		}
	}
	return 1;
}

int main()
{
	int T;
	T = gi();
	while(T--)
	{
		n = gi();
		rep(i,1,n)
		{
			v1[i].clear();	
			v2[i].clear();
		}
		rep(i,1,n)
		{
			scanf("%s",s+1);
			rep(j,1,n)
			{
				if(s[j] == 'P'){
					v1[i].push_back(j);
				} 
				else if(s[j] == 'Q'){
					v2[i].push_back(j);	
				} 
			}
		}
		int jud = 1;
		rep(i,1,n)
		{
			if(!solve1(i))
			{
				jud = 0; break;
			}
		}
		if(jud == 1)
		{
			rep(i,1,n)
			{
				if(!solve2(i))
				{
					jud = 0; break;
				}
			}
		}
		if(jud == 1) printf("T\n");
		else printf("N\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41552508/article/details/82012845