解题思路
题目的意思很明显,就是让判断一个图是不是一个连通图。这里测试一下(tarjan)算法求强连通分量的模板。
代码
const int maxn = 1e4+10;
const int maxm = 1e5+10;
struct {
int to, nex;
} e[maxm<<1];
int h[maxn], ecnt;
void ae(int u, int v) {
e[ecnt].to = v;
e[ecnt].nex = h[u];
h[u] = ecnt++;
}
int dfn[maxn], dfncnt; //访问过的点&&编号
int low[maxn]; //可以指向的最小编号的点
int sk[maxn], tp; //模拟栈
int scc[maxn], sc; //强连通分量&&编号
int sz[maxn]; //强连通分量的大小
void tarjan(int u) {
sk[++tp] = u;
low[u] = dfn[u] = ++dfncnt;
for (int i = h[u]; i; i = e[i].nex) {
int v = e[i].to;
if (!dfn[v]) { //未访问过
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (!scc[v]) //访问过并且还在栈中
low[u] = min(low[u], dfn[v]);
}
if (dfn[u]==low[u]) {
++sc;
while(true) { //给同一个联通分量内的点标记&&计算大小
int v = sk[tp--];
scc[v] = sc;
++sz[sc];
if (u==v) break;
}
}
return;
}
int main() {
int n, m, u, v;
while(~scanf("%d%d", &n, &m) && (n||m)) {
zero(dfn); zero(low); zero(scc); zero(sz); zero(h);
dfncnt = tp = sc = 0; ecnt = 1;
for (int i = 0; i<m; ++i) {
scanf("%d%d", &u, &v);
ae(u, v);
}
for (int i = 1; i<=n; ++i)
if (!dfn[i]) tarjan(i);
printf("%s
", sc==1?"Yes":"No");
}
return 0;
}