HDU - 5961 <-题目链接
思路:
思路1:随机化
这题不能随机答案并输出,20组数据几率还是太小了点。
我们想,它是个完全图,又是单向的,数据生成应该也不太好构造,2000*2000呢,所以我们想是不是可以随机化水一水。
srand(time(NULL));
每次随机三个数,然后我们检验这三个数的连通性。这个随机不一定是对的,因为最终图里可能只有一个小区域不符合连通性,所以我们多随机几次,我取的是400W次,交了两次过了。赛后100W交了3次过了。
check部分:
bool check(int x,int y,int z)
{
if(mapp[x][y] && mapp[y][z] && !mapp[x][z]) {return false;}
if(mapp[z][y] && mapp[y][x] && !mapp[z][x]) {return false;}
if(mapp[x][z] && mapp[z][y] && !mapp[x][y]) {return false;}
if(mapp[y][z] && mapp[z][x] && !mapp[y][x]) {return false;}
if(mapp[y][x] && mapp[x][z] && !mapp[y][z]) {return false;}
if(mapp[z][x] && mapp[x][y] && !mapp[z][y]) {return false;}
if(mapq[x][y] && mapq[y][z] && !mapq[x][z]) {return false;}
if(mapq[z][y] && mapq[y][x] && !mapq[z][x]) {return false;}
if(mapq[x][z] && mapq[z][y] && !mapq[x][y]) {return false;}
if(mapq[y][z] && mapq[z][x] && !mapq[y][x]) {return false;}
if(mapq[y][x] && mapq[x][z] && !mapq[y][z]) {return false;}
if(mapq[z][x] && mapq[x][y] && !mapq[z][y]) {return false;}
return true;
}
随机化部分:
bool flag = 1;
for(int i = 1;i <= 4000000;i ++)
{
int x = rand()%n+1;
int y = rand()%n+1;
while(y == x) y = rand()%n+1;
int z = rand()%n+1;
while(z == x || z == y) z = rand()%n+1;
if(!check(x,y,z))
{
// printf("x,y,z : %d %d %d\n",x,y,z);
flag = 0;
break;
}
}
if(flag) printf("T\n");
else printf("N\n");
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<ctime>
#define up(i,x,y) for(int i = x;i <= y;i ++)
#define down(i,x,y) for(int i = x;i >= y;i --)
#define mem(a,b) memset((a),(b),sizeof(a))
#define mod(x) ((x)%MOD)
#define lson p<<1
#define rson p<<1|1
using namespace std;
typedef long long ll;
const int SIZE = 2020;
const int INF = 2147483640;
const double eps = 1e-8;
inline void RD(int &x)
{
x = 0; char c; c = getchar();
bool flag = 0;
if(c == '-') flag = 1;
while(c < '0' || c > '9') {if(c == '-') {flag = 1;} c = getchar();}
while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0',c = getchar();
}
int t;
char maps[SIZE][SIZE];
bool mapp[SIZE][SIZE],mapq[SIZE][SIZE];
bool check(int x,int y,int z)
{
if(mapp[x][y] && mapp[y][z] && !mapp[x][z]) {return false;}
if(mapp[z][y] && mapp[y][x] && !mapp[z][x]) {return false;}
if(mapp[x][z] && mapp[z][y] && !mapp[x][y]) {return false;}
if(mapp[y][z] && mapp[z][x] && !mapp[y][x]) {return false;}
if(mapp[y][x] && mapp[x][z] && !mapp[y][z]) {return false;}
if(mapp[z][x] && mapp[x][y] && !mapp[z][y]) {return false;}
if(mapq[x][y] && mapq[y][z] && !mapq[x][z]) {return false;}
if(mapq[z][y] && mapq[y][x] && !mapq[z][x]) {return false;}
if(mapq[x][z] && mapq[z][y] && !mapq[x][y]) {return false;}
if(mapq[y][z] && mapq[z][x] && !mapq[y][x]) {return false;}
if(mapq[y][x] && mapq[x][z] && !mapq[y][z]) {return false;}
if(mapq[z][x] && mapq[x][y] && !mapq[z][y]) {return false;}
return true;
}
int main(int argc, char const *argv[])
{
//qaqaqqaqqaq
srand(time(NULL));
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i ++) scanf("\n%s",maps[i]+1);
for(int i = 1;i <= n;i ++)
{
for(int j = 1;j <= n;j ++)
{
if(maps[i][j] == 'P') mapp[i][j] = 1;
else mapp[i][j] = 0;
if(maps[i][j] == 'Q') mapq[i][j] = 1;
else mapq[i][j] = 0;
}
}
bool flag = 1;
for(int i = 1;i <= 4000000;i ++)
{
int x = rand()%n+1;
int y = rand()%n+1;
while(y == x) y = rand()%n+1;
int z = rand()%n+1;
while(z == x || z == y) z = rand()%n+1;
if(!check(x,y,z))
{
// printf("x,y,z : %d %d %d\n",x,y,z);
flag = 0;
break;
}
}
if(flag) printf("T\n");
else printf("N\n");
}
return 0;
}
/*
1
4
-PPP
--QQ
----
--Q-
*/
方法2:暴力
暴力1:floyd优化。没看= = 有人这么写的。
暴力2:BFS层次。对每个点BFS,如果有深度大于1的儿子则是不满足的,最终如果都深度为1,则满足。
虽然跑的很快但我觉得还是很像暴力。。
方法3:正解
给定的图是个竞赛图且两图没有公共边。这就让我们疑惑这个性质到底怎么用?
正确的用法是,将PQ合并判环,再将P(~Q)合并判环,最终如果都没有则满足题目条件。
证明:一句话,不满足连通性的条件一定是a->b,b->c,而不存在a->c,又因为是完全图,那么另一条边一定在Q图里,但是方向未知,不过反正就只有两个方向,枚举两个方向,肯定有一个有环,有环就不满足条件。