这道题用到了强连通分量的知识,实际上subtask A 是要求我们求最小点基的数量(最小点基的概念可以参考《ACM—ICPC程序设计系列 图论及应用》(哈尔滨工业大学出版社)P125)。当然,你不知道也不影响解题;subtask B 是要求我们将DAG转化成强连通图。
大体思路:首先用你擅长的强连通算法求出强连通分量,然后将每个分量缩成一个点,并将边的关系也转移到那个点上,分量内部的边舍去。当然这一步并不需要你真的按上面的说法做,可以用变通的方法,具体参考下面的代码。此时形成一个DAG,判断入度为0的点的个数,就是第一个任务的答案。而第二个任务的答案是max(n,m),具体参考http://www.cnblogs.com/kuangbin/archive/2011/08/07/2130277.html,这个可以想象一下加以理解。
这道题将DAG转化成强连通图的方法值得学习。做题与写博客间隔的太久了,要注意的地方不太记得了,好像要注意本来就是强连通图的情况。
代码(C++):
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define MAXp 109
#define MAXe 10000
using namespace std;
//#define LOCAL
struct Edge{
int u;
int v;
int next;
} edge[MAXe];
int head[MAXp],ts[MAXp],stk1[MAXp],stk2[MAXp],s1,s2,tcc,t,part[MAXp],c;
void addEdge(int u,int v)
{
edge[c].u=u;
edge[c].v=v;
edge[c].next=head[u];
head[u]=c;
c++;
}
void Gabow(int u)
{
int i,v;
ts[u]=t++;
stk1[++s1]=stk2[++s2]=u;
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(ts[v]==0)
{
Gabow(v);
}else if(part[v]==0)
{
while(ts[v]<stk2[s2]) s2--;
}
}
if(u==stk2[s2])
{
part[u]=++tcc;
while(stk1[s1]!=stk2[s2])
{
part[stk1[s1]]=tcc;
s1--;
}
s1--;
s2--;
}
}
int main(int argc, char *argv[]) //边从0开始编号,点从1开始编号
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int n,i,u,v,p;
int ideg[MAXp],odeg[MAXp],a,b;
while(scanf("%d",&n)!=EOF)
{
c=0;
memset(head,-1,sizeof(head));
for(u=1;u<=n;u++)
{
while(scanf("%d",&v)&&v!=0) addEdge(u,v);
}
s1=s2=-1;
tcc=0;
t=1;
memset(ts,0,sizeof(ts));
memset(part,0,sizeof(part));
for(p=1;p<=n;p++)
{
if(ts[p]==0) Gabow(p);
}
//for(i=1;i<=n;i++) cout<<part[i]<<'\t';
if(tcc==1)
{
printf("1\n0\n");
}else{
memset(ideg,0,sizeof(ideg));
memset(odeg,0,sizeof(odeg));
a=b=0;
for(i=0;i<c;i++)
{
u=edge[i].u;
v=edge[i].v;
if(part[u]!=part[v])
{
odeg[part[u]]++;
ideg[part[v]]++;
}
}
for(i=1;i<=tcc;i++)
{
if(odeg[i]==0) a++;
if(ideg[i]==0) b++;
}
printf("%d\n%d\n",b,max(a,b));
}
}
system("PAUSE");
return EXIT_SUCCESS;
}
Network of Schools
Time Limit: 1000MS | Memory Limit: 10000K | |
Description
A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B is in the distribution list of school A, then A does not necessarily appear in the list of school B
You are to write a program that computes the minimal number of schools that must receive a copy of the new software in order for the software to reach all schools in the network according to the agreement (Subtask A). As a further task, we want to ensure that by sending the copy of new software to an arbitrary school, this software will reach all schools in the network. To achieve this goal we may have to extend the lists of receivers by new members. Compute the minimal number of extensions that have to be made so that whatever school we send the new software to, it will reach all other schools (Subtask B). One extension means introducing one new member into the list of receivers of one school.
You are to write a program that computes the minimal number of schools that must receive a copy of the new software in order for the software to reach all schools in the network according to the agreement (Subtask A). As a further task, we want to ensure that by sending the copy of new software to an arbitrary school, this software will reach all schools in the network. To achieve this goal we may have to extend the lists of receivers by new members. Compute the minimal number of extensions that have to be made so that whatever school we send the new software to, it will reach all other schools (Subtask B). One extension means introducing one new member into the list of receivers of one school.
Input
The first line contains an integer N: the number of schools in the network (2 <= N <= 100). The schools are identified by the first N positive integers. Each of the next N lines describes a list of receivers. The line i+1 contains the identifiers of the receivers of school i. Each list ends with a 0. An empty list contains a 0 alone in the line.
Output
Your program should write two lines to the standard output. The first line should contain one positive integer: the solution of subtask A. The second line should contain the solution of subtask B.
Sample Input
5 2 4 3 0 4 5 0 0 0 1 0
Sample Output
1 2