Recall the definition of the median of elements where is odd: sort these elements and the median is the
-th largest element.
In this problem, the exact value of each element is not given, but relations between some pair of elements are given. The -th relation can be described as , which indicates that the -th element is strictly larger than the -th element.
For all , is it possible to assign values to each element so that all the relations are satisfied and the -th element is the median of the elements?
Input
There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:
The first line contains two integers and (, ), indicating the number of elements and the number of relations. It's guaranteed that is odd.
For the following lines, the -th line contains two integers and , indicating that the -th element is strictly larger than the -th element. It guaranteed that for all , or .
It's guaranteed that the sum of of all test cases will not exceed .
Output
For each test case output one line containing one string of length . If it is possible to assign values to each element so that all the relations are satisfied and the -th element is the median, the -th character of the string should be '1', otherwise it should be '0'.
看到两点之间有关系的时候,第一反应是拓扑排序,想着求出可能的顺序。
通过分析,发现了 一个点可以当做中点 的条件是 上面点的数量和下面点的数量 存在相等的可能。
拓扑排序:有两种关系,一种就是确定的关系,一种是不确定的关系。
图中给出的都是确定的关系,我们只关心确定的关系有多少,【也就是求 含有 点 的图中 有多少个点,这些点都是和
确定关系的 】
: 肯定比
大 的有多少点
: 肯定比
小 的有多少点
对于其他和 不确定关系的点,他们可以放在上面,也可以放在下面。
填充的时候,如果 的绝对值,小于等于不确定关系的点,我们就可以填充,或者
都小于
只需要求出 即可,通过dfs求出
【注:判断环的时候,要注意是正在访问的点,不是已经访问完成的点】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i=a;i<b;++i)
int n,m;
const int N=110;
vector<int> Edge[N];
vector<int> OEdge[N];
int vis[N];
int n1,n2;
int wrong;
void dfs(int x){
vis[x]=1;
for(int i=0;i<Edge[x].size();i++){
int v=Edge[x][i];
if(vis[v]==1){
wrong=1;return;
}
if(vis[v]==-1){
n1++;
dfs(v);
}
}
vis[x]=0;
}
void Odfs(int x){
vis[x]=1;
for(int i=0;i<OEdge[x].size();i++){
int v=OEdge[x][i];
if(vis[v]==1){
wrong=1;return;
}
if(vis[v]==-1){
n2++;
Odfs(v);
}
}
vis[x]=0;
}
/*
2
5 4
1 2
3 2
2 4
2 5
3 2
1 1
2 3
7 8
1 2
1 3
2 4
3 4
4 5
4 7
5 6
7 6
3 0
4 4
1 2
1 3
2 4
3 4
*/
int main(){
int T;
scanf("%d",&T);
rep(kase,0,T){
scanf("%d %d",&n,&m);
rep(i,1,n+1){
Edge[i].clear();
OEdge[i].clear();
vis[i]=-1;
}
wrong=0;
rep(i,0,m){
int u,v;
scanf("%d %d",&u,&v);
Edge[u].push_back(v);
OEdge[v].push_back(u);
if(u==v)wrong=1;
}
rep(i,1,n+1){
n1=0,n2=0;
rep(j,1,n+1)vis[j]=-1;
dfs(i);
rep(j,1,n+1)vis[j]=-1;
Odfs(i);
int t=n-n1-n2-1;
// printf("wrong:%d n1:%d %d\n",wrong,n1,n2);
if(!wrong&&t>=abs(n1-n2)){
printf("1");
}else{
printf("0");
}
}
printf("\n");
}
return 0;
}
也可以通过传递闭包的方式,将关系传递给所有可以确定的有序对。
利用warshall算法。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i,a,b) for(int i=a;i<b;++i)
const int N=110;
int mat[N][N],res[N];
/*
100
5 4
1 2
3 2
2 4
2 5
3 2
1 1
2 3
*/
int main(){
int T;
scanf("%d",&T);
rep(kase,0,T){
int n,m;
scanf("%d %d",&n,&m);
rep(i,1,n+1){
rep(j,1,n+1)mat[i][j]=0;
}
rep(i,0,m){
int u,v;
scanf("%d %d",&u,&v);
mat[u][v]=1;
}
rep(k,1,n+1){
rep(i,1,n+1){
rep(j,1,n+1){
mat[i][j]=mat[i][j]|(mat[i][k]&mat[k][j]);
}
}
}
/*
rep(i,1,n+1){
rep(j,1,n+1)printf("%d",mat[i][j]);
printf("\n");
}
*/
int wrong=0;
rep(i,1,n+1){
if(mat[i][i]==1){
wrong=1;break;
}
int n1=0,n2=0;
rep(j,1,n+1){
if(mat[i][j]&mat[j][i]){
wrong=1;break;
}
if(mat[i][j])n1++;
if(mat[j][i])n2++;
}
if(n-n1-n2-1>=abs(n1-n2))res[i]=1;
else res[i]=0;
}
if(wrong)rep(i,0,n)printf("0");
else rep(i,1,n+1)printf("%d",res[i]);
printf("\n");
}
return 0;
}
错误点:
1.忘记初始化
2.环的判断错误
3.代码位置不当,导致问题。
4.没看时间复杂度。
思路:
当时关注点没在 一点上,想图有多少种情况,想着想着就蒙了,该考虑核心的 中点