zoukankan      html  css  js  c++  java
  • HDU

    先上题目:

    Summer Holiday

    Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1337    Accepted Submission(s): 607


    Problem Description
    To see a World in a Grain of Sand 
    And a Heaven in a Wild Flower, 
    Hold Infinity in the palm of your hand 
    And Eternity in an hour. 
                      —— William Blake

    听说lcy帮大家预定了新马泰7日游,Wiskey真是高兴的夜不能寐啊,他想着得快点把这消息告诉大家,虽然他手上有所有人的联系方式,但是一个一个联系过去实在太耗时间和电话费了。他知道其他人也有一些别人的联系方式,这样他可以通知其他人,再让其他人帮忙通知一下别人。你能帮Wiskey计算出至少要通知多少人,至少得花多少电话费就能让所有人都被通知到吗?
     
    Input
    多组测试数组,以EOF结束。
    第一行两个整数N和M(1<=N<=1000, 1<=M<=2000),表示人数和联系对数。
    接下一行有N个整数,表示Wiskey联系第i个人的电话费用。
    接着有M行,每行有两个整数X,Y,表示X能联系到Y,但是不表示Y也能联系X。
     
    Output
    输出最小联系人数和最小花费。
    每个CASE输出答案一行。
     
    Sample Input
    12 16
    2 2 2 2 2 2 2 2 2 2 2 2
    1 3
    3 2
    2 1
    3 4
    2 4
    3 5
    5 4
    4 6
    6 4
    7 4
    7 12
    7 8
    8 7
    8 9
    10 9
    11 10
     
    Sample Output
    3 6
     
      中文题意不解释。这一条题需要使用缩点,对于同一个强连通分量里面因为任何的点都是可达的,所以对于这一个强连通分量里面的点,只需要找花费最小的那个点就可以了。同时不同的强连通分量之间也可能会有边相连,所以缩点以后,我们只需要找出缩点入度为零的点,这些位置就是需要联系的人。同时还需要注意给出的数据有可能是一个森林。
      这里我用了Tarjan缩点,第一次使用,还是有点地方不是很熟悉,或者说还有一点地方不是很了解。
      需要注意一下的地方有:①同一个强连通分量里面的点的low不一定是一样的。②节点是否已经访问和节点是否在栈中并不是等价的,所以需要分开来判断。
      关于强连通分量,还需要训练一下,再总结一下。
     
    上代码:
     
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <stack>
      4 #define min(x,y) (x < y ? x : y)
      5 #define MAX 2002
      6 #define INF 1000000000
      7 using namespace std;
      8 
      9 int n,m,id,index;
     10 int p[MAX>>1];
     11 int c[MAX>>1];
     12 int belong[MAX>>1];
     13 int dfn[MAX>>1],low[MAX>>1];
     14 bool instack[MAX>>1];
     15 
     16 stack<int> s;
     17 typedef struct{
     18     int from;
     19     int to;
     20     int next;
     21 }Edge;
     22 Edge e[MAX];
     23 int tot;
     24 int in[MAX>>1],les[MAX>>1];
     25 
     26 void add(int u,int v){
     27     e[tot].next=p[u];   e[tot].from=u;  e[tot].to=v;    p[u]=tot++;
     28 }
     29 
     30 void reset(){
     31     id=0;
     32     index=0;
     33     while(!s.empty()) s.pop();
     34     memset(c,0,sizeof(c));
     35     memset(p,-1,sizeof(p));
     36     memset(e,0,sizeof(e));
     37     memset(belong,0,sizeof(belong));
     38     memset(dfn,0,sizeof(dfn));
     39     memset(low,0,sizeof(low));
     40     memset(in,0,sizeof(in));
     41     memset(instack,0,sizeof(instack));
     42     tot=0;
     43 }
     44 
     45 void tarjan(int u){
     46     dfn[u]=low[u]=++id;
     47     s.push(u);
     48     instack[u]=1;
     49     for(int v=p[u];v!=-1;v=e[v].next){
     50         if(dfn[e[v].to]==0){
     51             tarjan(e[v].to);
     52             low[u]=min(low[u],low[e[v].to]);
     53         }else if(instack[e[v].to]){
     54             low[u]=min(low[u],dfn[e[v].to]);
     55         }
     56     }
     57     if(dfn[u]==low[u]){
     58         int v;
     59         index++;
     60         les[index]=c[u];
     61         do{
     62             v=s.top();
     63             belong[v]=index;
     64             les[index]=min(les[index],c[v]);
     65             instack[v]=0;
     66             s.pop();
     67         }while(u!=v);
     68     }
     69 }
     70 
     71 int main()
     72 {
     73     int x,y,minn,count;
     74     //freopen("data.txt","r",stdin);
     75     while(scanf("%d %d",&n,&m)!=EOF){
     76         reset();
     77         for(int i=1;i<=n;i++){
     78                 scanf("%d",&c[i]);
     79         }
     80         for(int i=1;i<=m;i++){
     81                 scanf("%d %d",&x,&y);
     82                 add(x,y);
     83         }
     84         for(int i=1;i<=n;i++){
     85             if(dfn[i]<=0) tarjan(i);
     86         }
     87         for(int i=0;i<tot;i++){
     88             int u,v;
     89             u=belong[e[i].from];
     90             v=belong[e[i].to];
     91             if(u!=v){
     92                 in[v]++;
     93             }
     94         }
     95         minn=0;
     96         count=0;
     97         for(int i=1;i<=index;i++){
     98             if(in[i]==0){
     99                 minn+=les[i];
    100                 count++;
    101             }
    102         }
    103         printf("%d %d
    ",count,minn);
    104     }
    105     return 0;
    106 }
    1827
  • 相关阅读:
    ZOJ2587 Unique Attack(判定最小割唯一性)
    SPOJ371 Boxes(最小费用最大流)
    SGU185 Two shortest(最小费用最大流/最大流)
    POJ2112 Optimal Milking(最大流)
    HDU3996 Gold Mine(最大权闭合子图)
    POJ3680 Intervals(最小费用最大流)
    SPOJ 7258 Lexicographical Substring Search(后缀自动机)
    HDU 4436 str2int(后缀自动机)
    SPOJ 1812 Longest Common Substring II(后缀自动机)
    CodeForces 235C Cyclical Quest(后缀自动机)
  • 原文地址:https://www.cnblogs.com/sineatos/p/3595321.html
Copyright © 2011-2022 走看看