zoukankan      html  css  js  c++  java
  • 考研路茫茫——空调教室 强连通 双联通分量

    Problem Description
    众所周知,HDU的考研教室是没有空调的,于是就苦了不少不去图书馆的考研仔们。Lele也是其中一个。而某教室旁边又摆着两个未装上的空调,更是引起人们无限YY。

    一个炎热的下午,Lele照例在教室睡觉的时候,竟然做起了空调教室的美梦。

    Lele梦到学校某天终于大发慈悲给某个教室安上了一个空调。而且建造了了M条通气管道,让整个教学楼的全部教室都直接或间接和空调教室连通上,构成了教室群,于是,全部教室都能吹到空调了。

    不仅仅这样,学校发现教室人数越来越多,单单一个空调已经不能满足大家的需求。于是,学校决定封闭掉一条通气管道,把全部教室分成两个连通的教室群,再在那个没有空调的教室群里添置一个空调。

    当然,为了让效果更好,学校想让这两个教室群里的学生人数尽量平衡。于是学校找到了你,问你封闭哪条通气管道,使得两个教室群的人数尽量平衡,并且输出人数差值的绝对值。
     
    Input
    本题目包含多组数据,请处理到文件结束。
    每组测试第一行包含两个整数N和M(0<N<=10000,0<M<20000)。其中N表示教室的数目(教室编号从0到N-1),M表示通气管道的数目。
    第二行有N个整数Vi(0<=Vi<=1000),分别代表每个教室的人数。
    接下来有M行,每行两个整数Ai,Bi(0<=Ai,Bi<N),表示教室Ai和教室Bi之间建了一个通气管道。
     
    Output
    对于每组数据,请在一行里面输出所求的差值。
    如果不管封闭哪条管道都不能把教室分成两个教室群,就输出"impossible"。
     
    Sample Input
    4 3 1 1 1 1 0 1 1 2 2 3 4 3 1 2 3 5 0 1 1 2 2 3
     
    Sample Output
    0 1

    用拓扑排序 各种数据都过了  死活wa

    #include<bits/stdc++.h>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define pb push_back
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 0x3f3f3f3f
    const int N=10000+5;
    const int M=2*N;
    int head[M],pos;
    struct Edge
    {
        int nex,to;
    }edge[M];
    void add(int a,int b)
    {
        edge[++pos].nex=head[a];
        head[a]=pos;
        edge[pos].to=b;
    }
    int tot,ind,cnt,Stack[N],dfn[N],low[N],vis[N],belong[N],node[N],peo[N],in[N];
    int n,m;
    vector<int>G[N];
    
    void init()
    {
        pos=tot=ind=cnt=0;
        CLR(Stack,0);
        CLR(in,0);
        CLR(peo,0);
        CLR(head,0);
        CLR(vis,0);
        CLR(dfn,0);
        CLR(low,0);
    }
    void tarjan(int x)
    {
        dfn[x]=low[x]=++tot;
        Stack[++ind]=x;
        vis[x]=1;
        for(int i=head[x];i;i=edge[i].nex)
        {
            int v=edge[i].to;
            if(!dfn[v])
            {
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(vis[v])
                low[x]=min(low[x],low[v]);
        }
        if(dfn[x]==low[x])
        {
            cnt++;int v;
            do
            {
                v=Stack[ind--];
                vis[v]=0;
                belong[v]=cnt;
                peo[cnt]+=node[v];
            }
            while(x!=v);
        }
    }
    
    int main()
    {
        while(~RII(n,m))
        {
            int sum=0;
            rep(i,1,n)RI(node[i]),sum+=node[i];
            rep(i,1,m)
            {
                int a,b;RII(a,b);
                a++;b++;
                add(a,b);
                add(b,a);
            }
            cnt=0;
            rep(i,1,n)
            if(!dfn[i])tarjan(i);
    
            int num=0;
            rep(i,1,n)
            {
                int u=belong[i];
                for(int j=head[i];j;j=edge[j].nex)
                {
                    int v=belong[ edge[j].to ];
                    if(u!=v)
                    {
                        int ok=1;
                        if(G[u].size())
                        rep(i,0,G[u].size()-1)
                        {
                            if(G[u][i]==v)ok=0;
                        }
                        if(ok)G[u].pb(v),in[v]++,num++;
                    }
                }
            }
    
            printf("cnt=%d num=%d
    ",cnt,num);
            if(num!=cnt-1||cnt==1)
                printf("impossible
    ");
            else
            {
                queue<int>q;
                CLR(node,0);
                rep(i,1,cnt)
                if(!in[i])
                {
                    node[i]=peo[i];
                    q.push(i);
                }
                int ans=inf;
                while(!q.empty())
                {
                    int u=q.front();q.pop();
                    ans=min(ans,abs( sum-node[u]-node[u]  ));
                    if(G[u].size())
                    rep(i,0,G[u].size()-1)
                    {
                        int v=G[u][i];
    
                        node[v]+=node[u];
                        ans=min(ans,abs( sum-node[v]-node[v]  ));
                        if(--in[v]==0)
                        {
                            node[v]+=peo[v];
                            ans=min(ans,abs( sum-node[v]-node[v]  ));
                            q.push(v);
                        }
                    }
                }
                printf("%d
    ",ans);
            }
            rep(i,1,cnt)
            G[i].clear();
            init();
    
        }
        return 0;
    }
    View Code

    原来是双联通分量  顶不住了 待补

    贴上大佬代码:

    #include<cstdio>
    #include<stack>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 10005;
    const int maxm = 20005;
    int n,m;
    int va[maxn];
    struct node
    {
        int to;
        int next;
        node(){}
        node(int a,int b):to(a),next(b){}
    }edge[maxm<<1],tree[maxm<<1];
    int head[maxn],dfn[maxn],low[maxn],belong[maxn],thead[maxn],ans[maxn];
    int tot,ti,coun,ttot,res,people;
    stack<int>s;
    void add_edge(int u,int v)
    {
        edge[tot] = node(v,head[u]);
        head[u] = tot++;
        edge[tot] = node(u,head[v]);
        head[v] = tot++;
    }
    void tarjan(int u,int fa)
    {
        dfn[u] = ++ti; low[u] = ti; s.push(u);
        int flag = 0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v = edge[i].to;
            if(v==fa&&flag==0){flag = 1;continue;}
            if(!dfn[v]){
                tarjan(v,u);
                low[u] = min(low[u],low[v]);
            }else if(belong[v]==-1) low[u] = min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            int y;
            coun++;
            do{
                y = s.top(); s.pop();
                ans[coun] += va[y];
                belong[y] = coun;
            }while(y!=u);
        }
    }
    int cbh(int u,int fa)
    {
        int sum = ans[u];
        dfn[u] = 1;
        for(int i=thead[u];i!=-1;i=tree[i].next)
        {
            int v = tree[i].to;
            if(v==fa||dfn[v]) continue;
            sum+=cbh(v,u);
        }
        res = min(res,abs(2*sum-people));
        return sum;
    }
    int main()
    {
        int u,v;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            people = 0;
            for(int i=0;i<n;i++) scanf("%d",&va[i]),people+=va[i];
            tot = 0;
            memset(head,-1,sizeof(head));
            for(int i=0;i<m;i++)
            {
               scanf("%d%d",&u,&v);
               add_edge(u,v);
            }
            memset(dfn,0,sizeof(dfn));
            memset(low,0,sizeof(low));
            memset(ans,0,sizeof(ans));
            memset(belong,-1,sizeof(belong));
            coun = 0;ti = 0;
            tarjan(0,0);
            if(coun==1){printf("impossible
    ");continue;}
          //  printf("%d
    ",coun);
            ttot = 0;
            memset(thead,-1,sizeof(thead));
            memset(dfn,0,sizeof(dfn));
            for(int i=0;i<n;i++)
            {
                for(int j=head[i];j!=-1;j=edge[j].next)
                {
                    v = edge[j].to;
                    if(belong[i]!=belong[v])
                    {
                        tree[ttot] = node(belong[v],thead[belong[i]]);
                        thead[belong[i]] = ttot++;
                    }
                }
            }
            res = 0xfffffff;
            cbh(1,0);
            printf("%d
    ",res);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    智能推荐算法演变及学习笔记(三):CTR预估模型综述
    从中国农业银行“雅典娜杯”数据挖掘大赛看金融行业数据分析与建模方法
    智能推荐算法演变及学习笔记(二):基于图模型的智能推荐(含知识图谱/图神经网络)
    (设计模式专题3)模板方法模式
    (设计模式专题2)策略模式
    (设计模式专题1)为什么要使用设计模式?
    关于macOS上常用操作命令(持续更新)
    记录下关于RabbitMQ常用知识点(持续更新)
    EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
    SpringCloud教程二:Ribbon(Finchley版)
  • 原文地址:https://www.cnblogs.com/bxd123/p/10800039.html
Copyright © 2011-2022 走看看