最小点基+最小权点基 (例题 Summer Holiday HDU - 1827)

概念

最高强连通分量:设si是有向图G中的一个强连通分量,如果该强连通分量与图G中其它强连通分量的所有弧都是向外延伸的,即该强连通分量入度为0,出度不为0,称之为最高强连通分量。

点基:在有向图 G=(V,E) 中,设B是V的子集,对于任意点y属于V,但不属于B,B中都存在一个点x是y的前代(即存在一条 x->y 的边),则称B是V的一个点基。

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

最小权点基:顶点对应的权值之和最小的点基。

 

算法

求最小点基:1、找出图G中的所以的强连通分量。

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

                  3、从每个最高强连通分量随便取一个点,这些点组成的点集就是一个最小点基。

 

求最小权点基:1、找出图G中的所以的强连通分量。

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

                     3、从每个最高强连通分量取一个权值最小的点,这些点组成的点集就是一个最小权点基。

 

例题

HDU 1827  Summer Holiday

就是裸的求最小点基和最小权点基

  1 //#include<bits/stdc++.h>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<string>
  7 #include<vector>
  8 #include<stack>
  9 #include<bitset>
 10 #include<cstdlib>
 11 #include<cmath>
 12 #include<set>
 13 #include<list>
 14 #include<deque>
 15 #include<map>
 16 #include<queue>
 17 #define ll long long
 18 #define MOD 1000000007
 19 #define INF 0x3f3f3f3f
 20 #define mem(a,x) memset(a,x,sizeof(a))
 21 #define lowbit(x) x&(-x)
 22 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
 23 using namespace std;
 24 
 25 int dfn[2005];
 26 int low[2005];
 27 int vis[2005];
 28 int stacks[2005];
 29 int color[2005];
 30 int cnt[2005];
 31 int deep,sum,top;
 32 int n,m;
 33 vector<int>g[2005];
 34 void tarjan(int u)
 35 {
 36     dfn[u]=++deep;
 37     low[u]=deep;
 38     vis[u]=1;
 39     stacks[++top]=u;
 40     for(int i=0;i<g[u].size();i++){
 41         int v=g[u][i];
 42         if(!dfn[v])
 43         {
 44             tarjan(v);
 45             low[u]=min(low[u],low[v]);
 46         }else{
 47             if(vis[v]){
 48                 low[u]=min(low[v],low[u]);
 49             }
 50         }
 51     }
 52     if(dfn[u]==low[u])
 53     {
 54         color[u]=++sum;
 55         vis[u]=0;
 56         while(stacks[top]!=u)
 57         {
 58             color[stacks[top]]=sum;
 59             vis[stacks[top--]]=0;
 60         }
 61         top--;
 62     }
 63 }
 64 int val[2005];
 65 int in[2005],out[2005];
 66 int main()
 67 {
 68     while(~scanf("%d %d",&n,&m)){
 69         deep=0;top=0;sum=0;
 70         for(int i=1;i<=n;i++){
 71             dfn[i]=0;vis[i]=0;low[i]=0;cnt[i]=0;
 72             in[i]=0;out[i]=0;
 73             g[i].clear();
 74         }
 75         for(int i=1;i<=n;i++){
 76             scanf("%d",&val[i]);
 77         }
 78         for(int i=1;i<=m;i++){
 79             int from,to;
 80             scanf("%d %d",&from,&to);
 81             g[from].push_back(to);
 82         }
 83         for(int i=1;i<=n;i++){
 84             if(!dfn[i]){
 85                 tarjan(i);
 86             }
 87         }
 88         for(int i=1;i<=n;i++){
 89             for(auto v:g[i]){
 90                 if(color[i]!=color[v]){
 91                     out[color[i]]++;
 92                     in[color[v]]++;
 93                 }
 94             }
 95         }
 96         ll num=0,ans=0;
 97         for(int i=1;i<=sum;i++){
 98             ll minn=INF;
 99             if(in[i]==0){
100                 num++;
101                 for(int j=1;j<=n;j++){
102                     if(color[j]==i){
103                         minn=min(minn,1ll*val[j]);
104                     }
105                 }
106                 ans+=minn;
107             }
108         }
109         printf("%lld %lld\n",num,ans);
110     }
111     return 0;
112 }

 

posted @ 2020-08-27 14:24  hachuochuo  阅读(275)  评论(0编辑  收藏  举报