题意:
给一个n个结点的有向图D,可以构造一个图E:D的每条边对应E的一个结点(例如,若D有一条边uv,则E有个结点的名字叫uv),对于D的两条边uv和vw,E中的两个结点uv和vw之间连一条有向边。E中不包含其他边。输入一个m个结点k条边的图E(0≤m≤300),判断是否存在对应的图D。E中各个结点的编号为0~m-1。
分析:
对于D中,a,b,c,d,e五个节点,存在ac,bc,cd,ce四条有向边,如果转换成E图的话,四条有向边会转化成四个结点,同时ac和cd,ac和ce,bc和cd,bc和ce之间会有有向边。则对于E图而言,如果存在i和j结点到k1都有边,而i和j中只有一个结点到k2有边,则这个图是不可能转化来的。因此暴力枚举i,j和k判断是否可行即可。代码很好写。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=300+5;
int T,n,m,x,y;
int map[maxn][maxn];
bool judge()
{
int i,j,k;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
int f1=0,f2=0;
for(k=0;k<n;k++)
{
if (map[i][k]&&map[j][k])
f1=1;
if (map[i][k]^map[j][k])
f2=1;
}
if(f1&&f2)
return false;
}
return true;
}
int main()
{
scanf("%d",&T);
for(int C=0;C<T;++C)
{
int i;
memset(map,0,sizeof(map));
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
map[x][y]=1;
}
printf("Case #%d: ",C+1);
if (judge())
printf("Yes ");
else
printf("No ");
}
return 0;
}