标签:class blog code http tar com
题目来源:Light OJ 1168 Wishing Snake
题意:有点难看懂题意 看了一个小时再加别人的代码才懂意思
从0开始 输入的那些每一对u v 都要经过 就是从0到到达那些点
思路:首先缩点 每一个强连通分量里面的点都是可达的
缩点后的图是有向无环图 如果从0这个强连通分量可以出去到2个强连通分量 那么这两个强连通分量是不可能相互可达
所以可行的方案就是所有的强连通分量连成一线 一个一个串起来 除了第一个 出度是1入度是0和最后一个出度是0入度是1 其他都是入度等于出度是1
特判只有一个强连通分量 和 开始第一个强连通分量是0所在的强连通分量
#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
const int maxn = 1010;
vector <int> G[maxn];
int pre[maxn];
int low[maxn];
int sccno[maxn];
int dfs_clock;
int scc_cnt;
stack <int> S;
int n, m;
int in[maxn];
int out[maxn];
int cnt[maxn];
int id[maxn];
void dfs(int u)
{
pre[u] = low[u] = ++dfs_clock;
S.push(u);
for(int i = 0; i < G[u].size(); i++)
{
int v = G[u][i];
if(!pre[v])
{
dfs(v);
low[u] = min(low[u], low[v]);
}
else if(!sccno[v])
low[u] = min(low[u], pre[v]);
}
if(pre[u] == low[u])
{
scc_cnt++;
while(1)
{
cnt[scc_cnt]++;
int x = S.top();
S.pop();
sccno[x] = scc_cnt;
if(x == u)
break;
}
}
}
void find_scc()
{
dfs_clock = scc_cnt = 0;
memset(sccno, 0, sizeof(sccno));
memset(pre, 0, sizeof(pre));
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i <= n; i++)
if(!pre[i])
dfs(i);
}
int main()
{
int cas = 1;
int T;
scanf("%d", &T);
while(T--)
{
memset(id, -1, sizeof(id));
scanf("%d", &m);
for(int i = 0; i <= 1000; i++)
G[i].clear();
n = 0;
id[0] = 0;
while(m--)
{
int k;
scanf("%d", &k);
while(k--)
{
int u, v;
scanf("%d %d", &u, &v);
if(id[u] == -1)
id[u] = ++n;
if(id[v] == -1)
id[v] = ++n;
G[id[u]].push_back(id[v]);
}
}
find_scc();
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
for(int i = 0; i <= n; i++)
{
for(int j = 0; j < G[i].size(); j++)
{
int v = G[i][j];
if(sccno[i] != sccno[v])
{
in[sccno[v]]++;
out[sccno[i]]++;
}
}
}
if(scc_cnt == 1)
{
printf("Case %d: YES\n", cas++);
continue;
}
if(in[sccno[0]] != 0 || out[sccno[0]] == 0)
{
printf("Case %d: NO\n", cas++);
continue;
}
int sum1 = 0, sum2 = 0, sum3 = 0;
for(int i = 1; i <= scc_cnt; i++)
{
if(in[i] == 1 && out[i] == 1)
sum1++;
else if(in[i] == 1 && out[i] == 0)
sum2++;
else if(in[i] == 0 && out[i] == 1)
sum3++;
}
if(sum2 != 1 || sum3 != 1 || sum1+sum2+sum3 != scc_cnt)
printf("Case %d: NO\n", cas++);
else
printf("Case %d: YES\n", cas++);
}
return 0;
}
Light OJ 1168 Wishing Snake 强连通缩点+哈密顿通路,布布扣,bubuko.com
Light OJ 1168 Wishing Snake 强连通缩点+哈密顿通路
标签:class blog code http tar com
原文地址:http://blog.csdn.net/u011686226/article/details/29400161