题意:给出n个点和m条边,接着给出直接相连的边(注意是有向边),求解任意x,y两点间是否存在x可到达y或者y可
到达x,如果任意x和y都满足这样的条件就输出"Yes",否则输出"No".
先求解出该有向图的强连通分量,然后根据求解出来的强连通分量进行缩点重新建图,
那么问题就转换为求解在新图中是否存在一条能走完所有的顶点的路径,这时可以对缩点后的新图进行拓扑排序,
看拓扑排序是否可以成功进行(可以通过在拓扑排序的过程中入度为0的顶点个数来进行判断),
如果存在拓扑排序并且是唯一的话说明缩点后的新图存在一条能走完所有顶点的路径.
到达x,如果任意x和y都满足这样的条件就输出"Yes",否则输出"No".
先求解出该有向图的强连通分量,然后根据求解出来的强连通分量进行缩点重新建图,
那么问题就转换为求解在新图中是否存在一条能走完所有的顶点的路径,这时可以对缩点后的新图进行拓扑排序,
看拓扑排序是否可以成功进行(可以通过在拓扑排序的过程中入度为0的顶点个数来进行判断),
如果存在拓扑排序并且是唯一的话说明缩点后的新图存在一条能走完所有顶点的路径.
考点:强连通、拓扑排序过程,返回是否成功,stack存拓扑排序的结果
调了很久啊。。。
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn=1005;
const int maxe=10005;
struct edge
{
int v,next;
void init(int tv,int tnext)
{
v=tv,next=tnext;
}
}e[maxe],newe[maxe];
int bfn[maxn],low[maxn];
int link[maxn],newlink[maxn];
int blg[maxn];
int deg[maxn];
int cnt,blgcnt,ne;
bool vis[maxn];
bool instack[maxn];
bool in[maxn][maxn];
stack<int> st;
void bfs(int u)
{
bfn[u]=low[u]=++cnt;
vis[u]=true;
st.push(u);
instack[u]=true;
int p,v;
for(p=link[u];p!=-1;p=e[p].next)
{
v=e[p].v;
if(!vis[v])
{
bfs(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v])
{
low[u]=min(low[u],bfn[v]);
}
}
if(bfn[u]==low[u])
{
blgcnt++;
do
{
v=st.top();
st.pop();
instack[v]=false;
blg[v]=blgcnt;
}while(v!=u);
}
}
void tarjan(int n)
{
cnt=blgcnt=0;
memset(vis,0,sizeof(vis));
memset(instack,0,sizeof(instack));
memset(blg,0,sizeof(blg));
int i;
for(i=1;i<=n;i++)
{
if(!vis[i])
{
bfs(i);
}
}
}
bool toposort(int n)
{
int i,j,sum,pos,p;
for(i=1;i<=n;i++)
{
sum=0;
pos=1;
for(j=1;j<=n;j++)
{
if(deg[j]==0)
{
sum++;
if(sum>1)
{
return false;
}
pos=j;
}
}
deg[pos]--;
for(p=newlink[pos];p!=-1;p=newe[p].next)
{
deg[newe[p].v]--;
}
}
return true;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
ne=0;
memset(link,-1,sizeof(link));
int i,j,u,v;
for(i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
e[ne].init(v,link[u]);
link[u]=ne++;
}
if(n==1)
{
puts("Yes");
continue;
}
tarjan(n);
memset(deg,0,sizeof(deg));
memset(in,0,sizeof(in));
memset(newlink,-1,sizeof(newlink));
ne=0;
for(i=1;i<=n;i++)
{
for(j=link[i];j!=-1;j=e[j].next)
{
u=blg[i];
v=blg[e[j].v];
if(v!=u&&!in[u][v])
{
in[u][v]=true;
newe[ne].init(v,newlink[u]);
newlink[u]=ne++;
deg[v]++;
}
}
}
if(toposort(blgcnt))
{
puts("Yes");
}
else
{
puts("No");
}
}
return 0;
}
9996

被折叠的 条评论
为什么被折叠?



