百度一下,发现这方面的资料太少。最小权点基貌似没有。

  这两类问题都需要强连通分量来解决。强连通的模版(三个)在我博客的模版分类中有。

点基:在有向图G=G,V)中,BV的子集。如果对于任意的y属于V,不属于B,都存在一个x属于B,使得xy的前代(有一条边从xy,则称B是一个点基。

PS:做题的时候间接相连也算。也就是有一条路径从xy

最小点基:顶点最少的点基。

最小权点基:顶点对应的权值之和最小的点基。(顶点权值非负)

最高强连通分量:顶点数目不能增加的强连通分量。(自己理解的)

求最小点基的步骤:

①找出图G的所有强连通分量。

②从强连通分量中找出所有的最高强连通分量。也就是缩点后入度为0的点。

③从每个最高强连通分量中任取一点,组成点集B就是一个最小点基。

 

求最小权点基的步骤:

①找出图G的所有强连通分量。

②从强连通分量中找出所有的最高强连通分量。也就是缩点后入度为0的点。

③从每个最高强连通分量中取权值最小的点,组成点集B就是一个最小点权基。

下面是求最小点基的一个例子。

poj1236

题目大意:

有N个学校,从每个学校都能从一个单向网络到另外一个学校,前代可以向后代(后代的后代)发送信息。

回答两个问题:
  1:至少需要向多少个学校发放软件,才能使得网络内所有的学校最终都能得到软件。
  2:至少需要添加几条边,才能使得任意一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。

第一问很显然就是求最小点基。

第二问就是问增加几条边以后可以使某个图成为强连通分量。经过测试,答案是max(a,b),其中a是入度为0的点的个数,b是出度为0的点的个数。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 const int N =110, M=50010;
  8 struct node
  9 {
 10     int to, next;;
 11 }edge[M];
 12 int head[N], low[N], dfn[N], sta[N], belg[N], num[N];
 13 bool vis[N];
 14 int scc,index,top, tot;
 15 void tarbfs(int u)
 16 {
 17     int i,j,k,v;
 18     low[u]=dfn[u]=++index;
 19     sta[top++]=u;
 20     vis[u]=1;
 21     for(i=head[u];i!=-1;i=edge[i].next)
 22     {
 23         v=edge[i].to;
 24         if(!dfn[v])
 25         {
 26             tarbfs(v);
 27             if(low[u]>low[v]) low[u]=low[v];
 28         }
 29         else if(vis[v]&&low[u]>dfn[v]) low[u]=dfn[v];
 30     }
 31     if(dfn[u]==low[u])
 32     {
 33         scc++;
 34         do
 35         {
 36             v=sta[--top];
 37             vis[v]=0;
 38             belg[v]=scc;
 39             num[scc]++;
 40         }
 41         while(v!=u) ;
 42     }
 43 }
 44 void Tarjan(int n)
 45 {
 46     memset(dfn,0,sizeof(dfn));
 47     memset(low,0,sizeof(low));
 48     memset(vis,0,sizeof(vis));
 49     index=scc=top=0;
 50     for(int i=1;i<=n;i++)
 51         if(!dfn[i]) tarbfs(i);
 52 }
 53 int od[N],id[N];
 54 void init()
 55 {
 56     tot=0;
 57     memset(head,-1,sizeof(head));
 58     memset(od,0,sizeof(od));
 59     memset(id,0,sizeof(id));
 60     memset(belg,0,sizeof(belg));
 61     memset(num,0,sizeof(num));
 62 }
 63 void addedge(int i,int j)
 64 {
 65     edge[tot].to=j; edge[tot].next=head[i];head[i]=tot++;
 66 }
 67 int main()
 68 {
 69     //freopen("test.txt","r",stdin);
 70     int n,i,j,a,b,c;
 71     while(scanf("%d",&n)!=EOF)
 72     {
 73         init();
 74         for(i=1;i<=n;i++)
 75         {
 76             while(scanf("%d",&a),a) {addedge(i,a);}
 77         }
 78         Tarjan(n);
 79         for(i=1;i<=n;i++)
 80         {
 81             for(j=head[i];j!=-1;j=edge[j].next)
 82             {
 83                 int u=edge[j].to;
 84                 if(belg[i]!=belg[u])
 85                 {
 86                     od[belg[i]]++;
 87                     id[belg[u]]++;
 88                 }
 89             }
 90         }
 91         if(scc==1) {printf("1\n0\n"); continue;}
 92         int ans=0;
 93         a=b=0;
 94         for(i=1;i<=scc;i++)
 95         {
 96             if(od[i]==0) a++;
 97             if(id[i]==0) b++;
 98         }
 99         printf("%d\n%d\n",b,max(a,b));
100     }
101     return 0;
102 }
View Code

相关文章:

  • 2022-12-23
  • 2021-09-27
  • 2021-10-15
  • 2021-06-14
  • 2022-01-29
  • 2022-12-23
  • 2022-02-11
猜你喜欢
  • 2021-12-01
  • 2022-12-23
  • 2022-12-23
  • 2021-07-19
  • 2022-12-23
  • 2021-05-17
  • 2022-12-23
相关资源
相似解决方案