BZOJ 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

 题解:暴力搜索+剪枝;

整理一下判断条件:

1.这一行是否有重复的数

2.这一列是否有重复的数

3.这一个小九宫格中是否有重复的数

4.是否符合大于小于的条件

现在我分别用 h[i][j] ,l[i][j] ,g[i][j] 来表示第i行,第i列,第i个小九宫格中数字j是否重复。还有一个大于小于号的问题后面再说,让我们先来看一下读入。

输入格式: 一共15行,包含一个新数独的实例。第奇数行包含左右方向的符号(<和>),第偶数行包含上下方向的符号(^和v)

说是奇数行包含左右方向的符号,偶数行包含上下方向的符号,其实如果你仔细的看一下题目或者样例输入的话,应该不难发现输入格式的描述略有问题,有的行与输入描述是相反的。。。(如果已经改过来了就当我没说)

其实可以这样看:输入是有15行的,你可以把这15行分成3组,每组5行,这样描述就对了,每一组的奇数行和偶数行按描述进行读入即可。

读入符号之后,先看这个符号属于哪一个小九宫格(因为不同小九宫格的符号是不相关的),然后就要用到下面这个数组了:

f[i][x][y]

它表示第i个小九宫格中第x个数和第y个数是否有大小关系。
读入的时候如果是”>”或者”v”就在相应的位置保存1,如果是”<“或”^”就保存2。

那么这样一来符号的问题就不是问题了,在选数的时候多加一个循环判断一下这个数周围的大小关系是否合法不就行了?

参考代码为:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int a[10][10],h[10][10],l[10][10],g[10][10],m,n,c,f[10][10][10]; 
void dfs(int x,int y)
{
    if(x==9&&y==10) 
    {
       for(int i=1;i<=9;++i) 
       {
        	for(int j=1;j<=9;++j) printf("%d ",a[i][j]);
        	cout<<endl;
       }
       return;
    }   
    if(y==10) x=x+1,y=1;
    for(int i=1;i<=9;++i)
    {   
        bool bl=0;
        int g1=((x-1)/3)*3,g2=(y-1)/3,g3=g1+g2;  
        if(g[g3][i]==1||h[x][i]==1||l[y][i]==1) continue;
        for(int j=1;j<=9;++j)
        {
            int ii=(x-1)%3*3+(y-1)%3+1;  
            if(f[g3][ii][j]==1) 
            {
                int xj=g3/3*3+(j-1)/3+1,yj=g3%3*3+(j-1)%3+1;  
                if(a[xj][yj]!=0)
                if(i<a[xj][yj]) 
				{
                    bl=1; 
					break;
                }
            }
            if(f[g3][ii][j]==2) 
            {
                int xj=g3/3*3+(j-1)/3+1,yj=g3%3*3+(j-1)%3+1;
                if(a[xj][yj]!=0)
                if(i>a[xj][yj])
				{
                    bl=1; 
					break;
                } 
            }     
        }
        if(bl==1) continue;
        g[g3][i]=1;h[x][i]=1;l[y][i]=1;
        a[x][y]=i;   
        dfs(x,y+1); 
        a[x][y]=0;   
        g[g3][i]=0;h[x][i]=0;l[y][i]=0;  
    }

}
int main()
{
    int ci=0;
    char s;
    for(int i=1;i<=3;++i)
    {
        for(int k=1;k<=5;++k)  
        {
            if(k%2==1)
            {
                for(int j=1;j<=6;++j)
                {
                    int q1=(i-1)*3,q2=(j-1)/2,q3=q1+q2; 
                    cin>>s;
                    if(s=='>')  
                    {
                        int qq=(k-1)/2*3+(j-1)%2+1; 
                        f[q3][qq][qq+1]=1;    
                        f[q3][qq+1][qq]=2;
                    }
                    else
                    {
                        int qq=(k-1)/2*3+(j-1)%2+1;
                        f[q3][qq][qq+1]=2;
                        f[q3][qq+1][qq]=1;
                    }
                }   
            }
            else
            {
                for(int j=1;j<=9;++j)
                {
                    int q1=(i-1)*3,q2=(j-1)/3,q3=q1+q2;
                    cin>>s;
                    if(s=='v')  
                    {
                        int qq=(k-1)/2*3+(j-1)%3+1;
                        f[q3][qq][qq+3]=1;
                        f[q3][qq+3][qq]=2;
                    } 
                    else
                    {
                        int qq=(k-1)/2*3+(j-1)%3+1;
                        f[q3][qq][qq+3]=2;
                        f[q3][qq+3][qq]=1;
                    }
                }   
            }
        }
    }
    dfs(1,1);
    return 0;
}