2 条题解
-
0
95分调了一个小时……
思路
很容易注意到如果有一个点入度大于等于,那么一定是不行的,因为一条边只能有一个方向。但是很快就注意到样例的第四个输入并不符合我们的想法。
不难注意到第四个输入的D图其实是同一个点上有三个自环,很明显原图的重边我们是需要排除的,所以就可以写出以下代码,十分简单(但是好像我讲的有点抽象)
AC代码
#include<bits/stdc++.h> using namespace std; const int N=310; vector<int>G[N]; bitset<N>a[N]; int rd[N]; bool v[N],used[N][N]; int main() { int T;scanf("%d",&T); while(T--) { memset(G,0,sizeof(G)); memset(a,0,sizeof(a)); memset(rd,0,sizeof(rd)); memset(v,0,sizeof(v)); memset(used,0,sizeof(used)); int n,m;scanf("%d%d",&n,&m); bool flag=0; for(int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y);x++;y++; if(used[x][y]){flag=1;} used[x][y]=1; G[x].push_back(y); a[x][y-1]=1;rd[y]++; } if(flag){puts("No");continue;} for(int i=1;i<=n;i++)if(!v[i])for(int j=i+1;j<=n;j++)if(a[i]==a[j]&&!v[j]) { v[j]=1; for(int w:G[j])rd[w]--; } bool bk=0; for(int i=1;i<=n;i++)if(rd[i]>1)bk=1; if(!bk)puts("Yes"); else puts("No"); } return 0; } -
0
大致思路就是:如果在图 D 中:,又有 ,那么在 E 中,, 都向 连边。此时如果存在另一个 使得 有边,则在 E 中 , 都应该向 有边。
也就是说,两个点指向一个公共的点,那么它们所有出边指向的点集必然相同,事实上这是存在 D 的充要条件,证明不难。
之前几篇题解要么用了并查集,要么用了数组暴力判断,这里提供一种不难想且速度不慢的方法:Bitset。
用 Bitset 记录邻接矩阵,枚举两行,算一下两行的与和异或,如果与不为 ,则说明指向公共点,此时再看异或,如果异或不为 ,说明出边不重合,答案为 No.
#include <bits/stdc++.h> using namespace std; const int MAXN=310; int t,n,m,x,y; bitset <MAXN> b[MAXN],tmp1,tmp2; int main () { scanf("%d",&t); for (int ii=1;ii<=t;ii++) { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) {b[i].reset();} for (int i=1;i<=m;i++) { scanf("%d%d",&x,&y); x++,y++; b[x].set(y); } int flg=0; for (int i=1;i<=n;i++) { if (flg) {break;} for (int j=1;j<=n;j++) { tmp1=b[i]&b[j],tmp2=b[i]^b[j]; if (tmp1.count()!=0&&tmp2.count()!=0) {flg=1;break;} } } printf("%s\n",flg?"No":"Yes"); } return 0; }
- 1
信息
- ID
- 4773
- 时间
- 500ms
- 内存
- 64MiB
- 难度
- 10
- 标签
- 递交数
- 11
- 已通过
- 2
- 上传者