zoukankan      html  css  js  c++  java
  • 蓝书3.5 强连通分量

    T1 受欢迎的牛  bzoj 1051

    题解链接

    T2 最大半连通子图 bzoj 1093

    题目大意:

    一个半连通的图定义为对任意点对u v 存在路径u->v或v->u

    求给定图的最大半连通子图

    思路:

    可以知道 半连通子图一定为强连通分量缩点之后的链

    所以只需要求一个最长链然后记一下方案数 需要注意第二次建图之后会有很多重边

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 2139062143
    10 #define ll long long
    11 #define MAXN 100100
    12 #define eps 1e-9
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n,m,mod,to[MAXN*10],nxt[MAXN*10],fst[MAXN],cnt;
    22 int To[MAXN*10],Nxt[MAXN*10],Fst[MAXN],dp[MAXN],ans,res,num[MAXN];
    23 int st[MAXN],top,dfn[MAXN],low[MAXN],scc,stp,vis[MAXN],sz[MAXN],bl[MAXN];
    24 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
    25 void Add(int u,int v) {Nxt[++cnt]=Fst[u],Fst[u]=cnt,To[cnt]=v;}
    26 void tarjan(int x)
    27 {
    28     dfn[x]=low[x]=++stp,st[++top]=x,vis[x]=1;
    29     for(int i=fst[x];i;i=nxt[i])
    30         if(!dfn[to[i]]) {tarjan(to[i]);low[x]=min(low[x],low[to[i]]);}
    31         else if(!bl[to[i]]) low[x]=min(low[x],dfn[to[i]]);
    32     if(low[x]==dfn[x])
    33     {
    34         scc++;int now=0;
    35         while(now!=x)
    36             now=st[top--],vis[now]=0,bl[now]=scc,sz[scc]++;
    37     }
    38 }
    39 void build()
    40 {
    41     for(int x=1;x<=n;x++)
    42         for(int i=fst[x];i;i=nxt[i])
    43             if(bl[to[i]]!=bl[x]) Add(bl[x],bl[to[i]]);
    44 }
    45 void dfs(int x)
    46 {
    47     vis[x]=num[x]=1;
    48     bool v[MAXN]={0};
    49     for(int i=Fst[x];i;i=Nxt[i])
    50     {
    51         if(v[To[i]]) continue;
    52         v[To[i]]=1;
    53         if(!vis[To[i]]) dfs(To[i]);
    54         if(dp[x]==dp[To[i]]) (num[x]+=num[To[i]])%=mod;
    55         else if(dp[To[i]]>dp[x]) num[x]=num[To[i]],dp[x]=dp[To[i]];
    56     }
    57     dp[x]+=sz[x],res=max(res,dp[x]);
    58 }
    59 int main()
    60 {
    61     n=read(),m=read(),mod=read();int a,b;
    62     while(m--) {a=read(),b=read();add(a,b);}
    63     for(int i=1;i<=n;i++)
    64         if(!dfn[i]) tarjan(i);
    65     cnt=0;build();
    66     for(int i=1;i<=scc;i++)
    67         if(!vis[i]) dfs(i);
    68     for(int i=1;i<=scc;i++) if(dp[i]==res) (ans+=num[i])%=mod;
    69     printf("%d
    %d",res,ans);
    70 }
    View Code

    T3 Network of Schools poj 1236

    题目大意:

    有向图 在图上的点染色 颜色会沿边运动 

    求最少给多少个点染色会使整个图都被染色以及最少再加多少边使给任意一点染色都可以使整张图被染色

    思路:

    第一问很明显是缩点后入度为0的点个数

    第二问应该讲每条链的首尾相接 因此答案为缩点后max(入度为0,出度为0)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 2139062143
    10 #define ll long long
    11 #define MAXN 10100
    12 #define eps 1e-9
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n,m,mod,to[MAXN<<1],nxt[MAXN<<1],fst[MAXN],cnt;
    22 int To[MAXN<<1],Nxt[MAXN<<1],Fst[MAXN],ans,res,Ind[MAXN],Od[MAXN];
    23 int st[MAXN],top,dfn[MAXN],low[MAXN],scc,stp,vis[MAXN],sz[MAXN],bl[MAXN];
    24 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
    25 void Add(int u,int v) {Nxt[++cnt]=Fst[u],Fst[u]=cnt,To[cnt]=v,Ind[v]++,Od[u]++;}
    26 void tarjan(int x)
    27 {
    28     dfn[x]=low[x]=++stp,st[++top]=x,vis[x]=1;
    29     for(int i=fst[x];i;i=nxt[i])
    30         if(!dfn[to[i]]) {tarjan(to[i]);low[x]=min(low[x],low[to[i]]);}
    31         else if(!bl[to[i]]) low[x]=min(low[x],dfn[to[i]]);
    32     if(low[x]==dfn[x])
    33     {
    34         scc++;int now=0;
    35         while(now!=x)
    36             now=st[top--],vis[now]=0,bl[now]=scc,sz[scc]++;
    37     }
    38 }
    39 void build()
    40 {
    41     for(int x=1;x<=n;x++)
    42         for(int i=fst[x];i;i=nxt[i])
    43             if(bl[to[i]]!=bl[x]) Add(bl[x],bl[to[i]]);
    44 }
    45 int main()
    46 {
    47     n=read();int a;
    48     for(int i=1;i<=n;i++) while(1) {a=read();if(!a) break;add(i,a);}
    49     for(int i=1;i<=n;i++)
    50         if(!dfn[i]) tarjan(i);
    51     cnt=0;build();
    52     for(int i=1;i<=scc;i++) if(!Ind[i]) ans++;
    53     for(int i=1;i<=scc;i++) if(!Od[i]) res++;
    54     if(scc==1) printf("1
    0");
    55     else printf("%d
    %d",ans,max(res,ans));
    56 }
    View Code

    T4 间谍网络 luogu 1262

    题目大意:

    有向图 有些点可以染色 颜色会沿边运动 这些点染色花费不同 

    求是否能将整张图染色 以及最小费用

    思路:

    缩点之后求出每个点是否能被染色以及最小费用 

    判断所有入度为0的点是否能被染色 将他们的费用加起来

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 2139062143
    10 #define ll long long
    11 #define MAXN 10100
    12 #define eps 1e-9
    13 using namespace std;
    14 inline int read()
    15 {
    16     int x=0,f=1;char ch=getchar();
    17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 int n,m,to[MAXN],nxt[MAXN],fst[MAXN],cnt,val[MAXN],ok[MAXN];
    22 int To[MAXN],Nxt[MAXN],Fst[MAXN],ans,res,cst[MAXN],Ind[MAXN],rep[MAXN];
    23 int st[MAXN],top,dfn[MAXN],low[MAXN],scc,stp,vis[MAXN],Ok[MAXN],bl[MAXN];
    24 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
    25 void Add(int u,int v) {Nxt[++cnt]=Fst[u],Fst[u]=cnt,To[cnt]=v,Ind[v]++;}
    26 void tarjan(int x)
    27 {
    28     dfn[x]=low[x]=++stp,st[++top]=x,vis[x]=1;
    29     for(int i=fst[x];i;i=nxt[i])
    30         if(!dfn[to[i]]) {tarjan(to[i]);low[x]=min(low[x],low[to[i]]);}
    31         else if(!bl[to[i]]) low[x]=min(low[x],dfn[to[i]]);
    32     if(low[x]==dfn[x])
    33     {
    34         scc++;int now=0;
    35         while(now!=x)
    36             now=st[top--],vis[now]=0,bl[now]=scc,Ok[scc]|=ok[now],cst[scc]=min(cst[scc],val[now]),rep[scc]=now;
    37     }
    38 }
    39 void build()
    40 {
    41     for(int x=1;x<=n;x++)
    42         for(int i=fst[x];i;i=nxt[i])
    43             if(bl[to[i]]!=bl[x]) Add(bl[x],bl[to[i]]);
    44 }
    45 int main()
    46 {
    47     memset(val,127,sizeof(val));memset(cst,127,sizeof(cst));
    48     n=read(),m=read();int a,b;
    49     while(m--) a=read(),ok[a]=1,val[a]=read();m=read();
    50     while(m--) {a=read(),b=read();add(a,b);}
    51     for(int i=1;i<=n;i++)
    52         if(!dfn[i]) tarjan(i);
    53     cnt=0;build();
    54     for(int i=1;i<=scc;i++) if(!Ind[i])
    55         if(!Ok[i]) {printf("NO
    %d",rep[i]);return 0;}
    56         else ans+=cst[i];
    57     printf("YES
    %d",ans);
    58 }
    View Code

    T5 Atm bzoj 1179

    题解链接

  • 相关阅读:
    Excel电子表格操作
    word文档编辑
    中英文输入
    个人借款合同范本
    Day-8:汇总数据
    Day-7:使用函数处理数据
    Day-6:创建计算字段
    Day-5:通配符过滤
    Day-4:高级数据过滤
    Day-3:过滤数据
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9372747.html
Copyright © 2011-2022 走看看