图论一直以来都很弱,又不懂什么最小点基(实现方法)……AC的时候……真爽啊。。。。。
| | | |
编译通过... ├ 测试数据 01:答案正确... 0ms ├ 测试数据 02:答案正确... 0ms ├ 测试数据 03:答案正确... 0ms ├ 测试数据 04:答案正确... 0ms ├ 测试数据 05:答案正确... 0ms ├ 测试数据 06:答案正确... 0ms ├ 测试数据 07:答案正确... 0ms ├ 测试数据 08:答案正确... 0ms ├ 测试数据 09:答案正确... 0ms ├ 测试数据 10:答案正确... 0ms ------------------------- Accepted 有效得分:100 有效耗时:0ms | | |
hoho~
先把题贴一下:
描述 Description | |
| Victoria是一位颇有成就的艺术家,他因油画作品《我爱北京天安门》闻名于世界。现在,他为了报答帮助他的同行们,准备开一个舞会。 Victoria准备邀请n个已经确定的人,可是问题来了: 这n个人每一个人都有一个小花名册,名册里面写着他能够通知到的人的名字。比如说在A的人名单里写了B,那么表示A能够通知到B;但是B的名单里不见的有A,也就是说B不见得通知到A。 Victoria觉得需要确定自己需要通知多少个人m,能够实际将所有人n都通知到。并求出一种方案以确定m的最小值是多少。 注意:自己的名单里面不会有自己的名字。Victoria可以自身通知到所有n个人。
|
| | |
| | |
| 输入格式 Input Format | |
| 第一行一个数n。接下来n行,每i+1行表示编号为i的人的小花名册名单,名单以0结束。1<=n<=200。
|
| | |
| | |
| 输出格式 Output Format | |
| 一个数,m。
|
| | |
| | |
| 样例输入 Sample Input | |
| 18 0 11 0 0 0 0 16 0 14 0 0 0 0 2 13 0 0 11 0 7 0 0 6 0 0 0 |
| | |
| | |
| 时间限制 Time Limitation | |
| 各个测试点1s
|
貌似有一个类似模拟的办法,VIJOS上有人说过了。
以下是我苦思冥想出来的成果,没想到一遍就AC了。
1 把原有向图G中强连通分量缩为一点
1.1 DFS(G),记录节点访问完成的顺序,也可以说是一次拓扑排序。
1.2 反转图每一条弧得到新图Gt。
1.3 按照1.1记录的顺序DFS(Gt),得到的森林里每一棵树都是一个强连通分量。(用并查集合并每一个访问到的节点,从而实现“缩”强连通分量)。得到一强连通分量为单位的图Gscc。
2 DFS(Gscc),再一次拓扑排序,记录强连通分量访问完成的顺序。
4 按照2记录的顺序DFS(Gscc),用并查集得到访问产生的森林。
5 统计最后森林中树的个数即可得到答案。
程序(K&R风格代码)有120+行的样子。。。
#include
<
stdio.h
>
#include
<
stdbool.h
>
void
toposort(
void
);
void
topovisit(
int
i);
void
reverse(
void
);
void
contract(
void
);
void
convisit(
int
i);
void
contract2(
void
);
void
convisit2(
int
i);
int
rank[
201
],
set
[
201
];
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
Makeset(
int
x)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
set[x]=x;
rank[x]=0;
}
int
Find(
int
x)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(set[x]!=x)
set[x]=Find(set[x]);
return set[x];
}
void
Link(
int
x,
int
y)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(rank[x]>rank[y])
set[y]=x;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
else...{
set[x]=y;
if(rank[x]==rank[y]) rank[y]++;
}
}
void
Union(
int
x,
int
y)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
Link(Find(x),Find(y));
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int
n,topo[
201
],p;
int
nc;
bool
gt[
201
][
201
],g[
201
][
201
],vis[
201
];
int
main(
void
)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int i,j,k;
int t,count=0;
FILE *fin=stdin;
fscanf(fin,"%d ",&n);
nc=n;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for(i=0;i<n;i++)...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while(1)...{
fscanf(fin,"%d", &t);
if(!t) break;
g[i][t-1]=true;
}
Makeset(i);
}
toposort();
reverse();
contract();
toposort();
contract2();
for(i=0;i<n;i++) if(set[i]==i) count++;
printf("%d ",count);
return 0;
}
void
toposort(
void
)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int i;
memset(vis,0,sizeof(vis));
p=0;
for(i=0;i<n;i++) if(!vis[i]) topovisit(i);
}
void
topovisit(
int
i)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int j;
vis[i]=true;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for(j=0;j<n;j++)...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(g[i][j] && Find(i)!=Find(j) && !vis[j])...{
topovisit(j);
}
}
topo[p++]=Find(i);
}
void
reverse(
void
)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(g[i][j]) gt[j][i]=true;
}
void
contract(
void
)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int j;
memset(vis,0,sizeof(vis));
for(j=0;j<n;j++) if (!vis[topo[j]]) convisit(topo[j]);
}
void
convisit(
int
i)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int j;
vis[i]=true;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for(j=0;j<n;j++)...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(gt[i][j] && !vis[j])...{
Union(i,j);
convisit(j);
}
}
}
void
contract2(
void
)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int j;
memset(vis,0,sizeof(vis));
for(j=0;j<p;j++) if (!vis[topo[j]]) convisit(topo[j]);
}
void
convisit2(
int
i)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int j;
vis[i]=true;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for(j=0;j<n;j++)...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(g[i][j] && !vis[j])...{
Union(i,j);
convisit(j);
}
}
}