题解 P2419 【[USACO08JAN]Cow Contest S】
一种不是拓扑排序也不是Floyd的玄学算法
目的
就拿样例来说吧:
我们其实可以从图中获得更多信息,比如1比5厉害等,所以我们希望它能把我们所有的已知信息都表现出来,像这样:
然后就可以方便地做判断了:哪个点的入度和出度之和
具体方法
先用矩阵存图,1指向2就把第一行第二列变成1,以此类推,得到:
然后要变成第二张图的样子(把所有已知信息表示出来),具体步骤:
如果
为什么呢?因为
最后,要如何判断点i能否和每个点都连边呢?其实很简单:只需要把第i行和第i列上的点都加起来,再减去1(点
为什么呢?因为第
算法比较难理解,有耐心的话可以仔细画画想想。
附上AC代码:
#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast")
#pragma GCC optimize("inline")
using namespace std;
bool a[110][110];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
a[x][y]=1;
}
for(int i=1;i<=n;i++)
a[i][i]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j])
{
for(int k=1;k<=n;k++)
if(k!=i&&a[k][i])
a[k][j]=1;
for(int k=1;k<=n;k++)
if(k!=j&&a[j][k])
a[i][k]=1;
}
int num=0;
for(int i=1;i<=n;i++)
{
int ans=0;
for(int j=1;j<=n;j++)
{
ans+=a[i][j];
ans+=a[j][i];
}
if(ans-1==n)
num++;
}
cout<<num<<endl;
return 0;
}