bzoj3108【CQOI2013】图的逆变换

3108: [cqoi2013]图的逆变换

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 424   Solved: 271
[ Submit][ Status][ Discuss]

Description

给一个n结点m条边的有向图D,可以这样构造图E:给D的每条边u->v,在E中建立一个点uv,然后对于D中的两条边u->v和v->w,在E中从uv向vw连一条有向边。E中不含有其他点和边。
输入E,你的任务是判断是否存在相应的D。注意,D可以有重边和自环。
 

Input

第一行包含测试数据个数T(T<=10)。每组数据前两行为D的边数(即E的点数)m和E的边数k(0<=m<=300)。以下k行每行两个整数x, y,表示E中有一条有向边x->y。E中的点编号为0~m-1。
 

Output

 
对于每组数据输出一行。如果存在,输出Yes,否则输出No。

Sample Input

4
2
1
0 1
5
0
4
3
0 1
2 1
2 3
3
9
0 1
0 2
1 2
1 0
2 0
2 1
0 0
1 1
2 2

Sample Output

Yes
Yes
No
Yes



模拟大水题...

无解的情况当且仅当有边x->y、x->z且存在t使得t只和y、z中的一个点有边相连。然后枚举判断一下就好了。




#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 305
using namespace std;
int t,n,m;
int e[maxn][maxn],tot[maxn];
bool f[maxn][maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void solve()
{
	n=read();m=read();
	memset(e,0,sizeof(e));
	memset(tot,0,sizeof(tot));
	memset(f,false,sizeof(f));
	F(i,1,m)
	{
		int x=read()+1,y=read()+1;
		if (!f[x][y]){f[x][y]=true;e[x][++tot[x]]=y;}
	}
	F(i,1,n) F(j,1,n) F(k,1,tot[i]-1)
	{
		int x=e[i][k],y=e[i][k+1];
		if (f[j][x]!=f[j][y]){puts("No");return;}
	}
	puts("Yes");
}
int main()
{
	t=read();
	while (t--) solve();
	return 0;
}


你可能感兴趣的:(bzoj)