• 强大的dfs(用处1——拓扑排序【xdoj1025】,用处二——求强联通分量【ccf高速公路】)当然dfs用处多着咧


    xdoj 1025

    亮亮最近在玩一款叫做“梦想庄园”的经营游戏。在游戏中,你可以耕种,养羊甚至建造纺织厂。
    如果你需要制造衣服,你首先得有布匹和毛线。布匹由棉花纺织而成;毛线由羊毛制成,而羊需要饲料才能长出羊毛,最终饲料由小麦和胡萝卜制成。
      假设游戏中共有N种物品,第i种物品由其他Ci个物品制成。亮亮需要你帮他制作M个任务物品来完成销售订单。
    游戏中的每个物品都有一个价格Vi,当原材料不足以制作出所有的物品时,你需要花尽量少的钱买一些物品来完成任务。你可以选择直接购买所需的任务物品,也可以购买其他物品来制作任务物品,但是每制作一次需要W的代价。
     

    题目分析:看着好吓人啊。。其实分析清晰也很简单。每种物体既可以直接买到或者由其他物体制作得到。那么我们就取两者的最小值。制作的花费我们可以这样求得
    如果x的原材料有y 那么x和y之间有一条有向边 。然后按照拓扑排序的顺序自底而上求出各个物体制作所需的价值。。很简单吗?!
     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <vector>
     6 using namespace std;
     7 const int N=1e4+7;
     8 vector < vector <int> > g(N);
     9 int val[N];
    10 bool vis[N];
    11 int n,m,w;
    12 void dfs (int rt) {
    13     vis[rt]=1;
    14     if (g[rt].size()==0) return ;// 最底层直接返回
    15     int cost=w;
    16     for (int i=0;i<g[rt].size();i++) {
    17         int next=g[rt][i];
    18         if (!vis[next])  dfs(next);
    19         cost+=val[next];//cost制作费用
    20     }
    21     val[rt]=min (cost,val[rt]);//取两者最小值
    22     return ;
    23 }
    24 int main ()
    25 {
    26     int T;
    27     scanf ("%d",&T);
    28     while (T--) {
    29         scanf ("%d %d %d",&n,&m,&w);
    30         for (int i=0;i<n;i++) g[i].clear();
    31         memset (vis,0,sizeof(vis));
    32         for (int i=0;i<n;i++) {
    33             scanf ("%d",&val[i]);
    34             int num; scanf ("%d",&num);
    35             for (int j=0;j<num;j++) {
    36                 int u; scanf ("%d",&u);
    37                 g[i].push_back(u);
    38             }
    39         }
    40         for (int i=0;i<n;i++) 
    41             if (!vis[i])  dfs (i);
    42         int sum=0;
    43         for (int i=0;i<m;i++) {
    44             int x; scanf ("%d",&x);
    45             sum+=val[x];
    46         }
    47         printf ("%d
    ",sum);
    48     }
    49     return 0;
    50 }

    ccf 高速公路 求联通分量 这个算法好像叫trajin 向这些科学家致敬

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <stack>
     5 #include <vector>
     6 using namespace std;
     7 const int N=1e4+7;
     8 vector < vector <int> > g(N);
     9 stack <int> ss;
    10 bool instack[N];
    11 bool vis[N];
    12 int dfn[N],low[N];// dfn 保存遍历序号  low 这个点所能到达的最小点  
    13 int ans;
    14 int n,m;
    15 int cnt;//访问顺序
    16 void dfs (int rt) {
    17     vis[rt]=1;
    18     instack[rt]=1; ss.push(rt);
    19     dfn[rt]=low[rt]=++cnt;
    20     for (int i=0;i<g[rt].size();i++) {
    21         int next=g[rt][i];
    22         if (!vis[next]) {
    23             dfs (next);
    24             low[rt]=min (low[rt],low[next]);
    25         }
    26         else if (instack[next]) {
    27             low[rt]=min (low[rt],low[next]);
    28         }
    29     }
    30     if (dfn[rt]==low[rt]) {// dfn[rt]==low[rt] 表示遍历一个联通分变量啦
    31         int num=1;
    32         int tmp=ss.top(); ss.pop(); instack[tmp]=0;//在栈中 说明这个点的后继子孙还没有访问完
    33         while (dfn[tmp]!=low[tmp]) { num++; tmp=ss.top(); ss.pop(); instack[tmp]=0;}
    34         ans+=(num-1)*num/2;
    35     }
    36     return ;
    37 }
    38 int main ()
    39 {
    40     ios::sync_with_stdio(false);
    41     cin>>n>>m;
    42     for (int i=1;i<=m;i++) {
    43         int x,y; cin>>x>>y;
    44         g[x].push_back(y);
    45     }
    46     for (int i=1;i<=n;i++)
    47         if (!vis[i]) dfs (i);
    48     printf ("%d
    ",ans);
    49     return 0;
    50 }
     
    抓住青春的尾巴。。。
  • 相关阅读:
    codefroces 946F Fibonacci String Subsequences
    [HNOI2010]MATRIX 矩阵
    [HNOI2010]STONE取石头游戏
    [HNOI2010]PLANAR
    [HNOI2010]BUS 公交线路
    [HNOI2010]CHORUS 合唱队
    [HNOI2011]赛车游戏
    [HNOI2011]数矩形
    [HNOI2012]与非
    [BZOJ4200][NOI2015]小园丁与老司机
  • 原文地址:https://www.cnblogs.com/xidian-mao/p/8511508.html
Copyright © 2020-2023  润新知