1. 程式人生 > >BZOJ 3108: [cqoi2013]圖的逆變換

BZOJ 3108: [cqoi2013]圖的逆變換

3108: [cqoi2013]圖的逆變換

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 627  Solved: 415
[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 ; z->y ; 則他們的終點相同,則在有 x->k 卻沒有 z->k(或則有z->k卻沒有x->k)這種情況是不存在的; 參考程式碼:
#include<bits/stdc++.h>
using namespace std;
#define clr(a,b) memset(a,b,sizeof a)
typedef long long ll;
const int base=310;
int T,m,k,u,v,mp[310][310];
bool solve()
{
	for(int i=1;i<=m;++i)
	{
		for(int j=i+1;j<=m;++j)
		{
			int f1=0,f2=0;
			for(int k=1;k<=m;++k)
			{
				if(mp[i][k]&&mp[j][k]) f1=1;
				if(mp[i][k]^mp[j][k]) f2=1;
				if(f1&&f2) return false;
			} 
		}
	}
	return true;
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		clr(mp,0);
		scanf("%d%d",&m,&k);
		for(int i=1;i<=k;++i)
		{
			scanf("%d%d",&u,&v);
			mp[++u][++v]=1;
		}
		if(solve()) printf("Yes\n");
		else printf("No\n");
	}
	
	return 0;
}