Time Limit: 2000MS | Memory Limit: 65536K | |
Description
Input
Output
Sample Input
1 3 3 1 2 2 3 3 1
Sample Output
Yes
题目大意:给定一个有向图,判断是否对任意两点u,v,有u可达v 或 v可达u?
先找出所有的强连通分量,则各强连通分量内是相互可达的,只用判断强连通分量之间是否至少单向可达
将各强连通分量缩成一点,建立新图,则新图是DAG
刚开始也认为只要从一个入度为0的点到出度为0的点的长度为总点数,就满足题意,否则不行,但是看见有人说不是只有一条链的情况下会输出Yes,于是放弃了
最终用拓扑排序AC,若某次队列中点的数目大于1(则这些点之间不能单向可达),则输出No,否则输出Yes
没有初始化indeg数组,导致WA了很久都没看出来...
#include
#include
#include
using namespace std;
const int MAXN=1005;
int n,m,num,cnt,ans,top,head,tail;
int stak[MAXN],que[MAXN];
int low[MAXN],dfn[MAXN],color[MAXN],indeg[MAXN];//biocks[i]表示删掉i点后,能形成的连通块数
vector g[MAXN];
bool isIn[MAXN],mp[MAXN][MAXN];
void Tarjan(int u,int p) {
stak[++top]=u;
isIn[u]=true;
dfn[u]=low[u]=++num;
int v;
for(int i=0;i1)//如果入度为0的点超过一个,则这些点不能相互单向可达
return false;
int u;
while(head!=tail) {
u=que[head++];
for(int i=1;i<=cnt;++i) {
if(mp[u][i]) {
--indeg[i];
if(indeg[i]==0)//入度为0的点入队
que[tail++]=i;
}
}
if(tail-head>1)//如果入度为0的点超过一个,则这些点不能相互单向可达
return false;
}
return true;
}
int main() {
int T,s,e;
scanf("%d",&T);
while(T-->0) {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) {
g[i].clear();
dfn[i]=indeg[i]=0;
isIn[i]=false;
}
while(m-->0) {
scanf("%d%d",&s,&e);
g[s].push_back(e);
}
cnt=num=top=0;//cnt表示强连通分量
for(int i=1;i<=n;++i) {
if(dfn[i]==0)
Tarjan(i,0);
}
memset(mp,false,sizeof(mp));
for(int i=1;i<=n;++i) {
for(int j=0;j
#include
#include
#include
using namespace std;
const int MAXN=1005;
int n,m,num,cnt,ans,top;
int stak[MAXN];
int low[MAXN],dfn[MAXN],color[MAXN],dp[MAXN];//biocks[i]表示删掉i点后,能形成的连通块数
vector g[MAXN],mp[MAXN];
bool isIn[MAXN],haveIndeg[MAXN];
void Tarjan(int u,int p) {
stak[++top]=u;
isIn[u]=true;
dfn[u]=low[u]=++num;
int v;
for(int i=0;i1)
return false;
dfs(sta);
return dp[sta]==cnt;//判断入度为0的点能达到的最大深度是否等于点的个数
}
int main() {
int T,s,e;
scanf("%d",&T);
while(T-->0) {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) {
g[i].clear();
mp[i].clear();
dfn[i]=0;
isIn[i]=haveIndeg[i]=false;
}
while(m-->0) {
scanf("%d%d",&s,&e);
g[s].push_back(e);
}
printf("%s\n",Judge()?"Yes":"No");
}
return 0;
}