题意:给一个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。(本段摘自《算法竞赛入门经典(第2版)》)
分析:
对于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<bits/stdc++.h>
using namespace std;
const int maxn=300+5;
int T,n,m,x,y;
int a[maxn][maxn];
bool judge()
{
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
{
bool f1 = false, f2 = false;
for (int k = 0; k < n; ++k)
{
if (a[i][k] && a[j][k])
f1 = true;
if (a[i][k] ^ a[j][k])
f2 = true;
}
if (f1 && f2)
return false;
}
return true;
}
int main()
{
scanf("%d",&T);
for(int C=0;C<T;++C){
memset(a,0,sizeof(a));
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
a[x][y]=1;
}
printf("Case #%d: ",C+1);
if (judge())
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
429

被折叠的 条评论
为什么被折叠?



