hdu5413

通过这道题新学了一个bitset,本来是用的数组,超空间,换成bitset就不超了,本来用的是循环,超时,换成bitset的操作,就不超时了,一定要把bitset拆开看看。

还有,虽然这次没用到,但是针对于递归太多爆栈,终于知道了要用 #pragma comment(linker,"/STACK:1024000000,1024000000").

这道题近似于暴力,只不过要转化一下。

代码参考:http://blog.csdn.net/u013007900/article/details/47842179

bitset参考:http://blog.163.com/lixiangqiu_9202/blog/static/53575037201251121331412/

      http://www.cnblogs.com/lvpengms/archive/2010/04/10/1708836.html

(昨天和队友偷偷的在宿舍吃了火锅,虽然过程坎坷,但是最后成功的吃到了!得意

2015.8.29:

给队友讲了这道题,所以对这道题印象挺深的,对于这道题,感叹,以前总感觉用那些现成的什么vector,set不算什么英雄好汉,上c++课说过这类已经写好的代码用处有限,还被老师给纠正了,现在感觉这些东西好神奇,都是天神(天上的大神,大神中的大神,大神中的战斗机)写出来的,希望自己也能写出这些,然后就能自己用自己的了,想想就小窃喜呢大笑

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<bitset>
using namespace std;
#define N 20010
#define M 100010
#pragma comment(linker, "/STACK:1024000000,1024000000")

//bool kd[N][N];
bitset<N> bs[N];//将bool换成bitset就不超空间了
int head[N],to[M],nextedge[M];
int order[N];
int fro[N];
int sq[N];
int cou;
int edge[M][2];

void add(int a,int b){
    to[cou]=b;nextedge[cou]=head[a];head[a]=cou++;
}

int main(){
    int t;
    int n,m;
    int a,b;
    int ans;

    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        cou=0;
        memset(head,-1,sizeof(head));
        //memset(kd,false,sizeof(kd));
        for(int i=1;i<=n;i++){
            bs[i].reset();
        }
        memset(fro,0,sizeof(fro));
        for(int i=0;i<m;i++){
            scanf("%d%d",&a,&b);
            edge[i][0]=a;
            edge[i][1]=b;
            add(a,b);
            fro[b]++;
        }

        int qend=0;
        int oend=0;
        for(int i=1;i<=n;i++){
            if(fro[i]==0){
                sq[qend++]=i;
                order[oend++]=i;
            }
        }

        while(qend!=0){
            int temp=sq[--qend];

            for(int i=head[temp];i!=-1;i=nextedge[i]){
                int v=to[i];
                fro[v]--;
                if(!fro[v]){
                    order[oend++]=v;
                    sq[qend++]=v;
                }
            }
        }

        /*for(int i=0;i<oend;i++){
            printf("%d ",order[i]);
        }
        printf("\n");*/

        for(int i=oend-1;i>=0;i--){//感觉是这里浪费了很多时间,应该要简化一下。
            int u=order[i];
            for(int j=head[u];j!=-1;j=nextedge[j]){
                int v=to[j];

                //kd[u][v]=true;
                bs[u][v]=1;
                /*for(int k=1;k<=n;k++){
                    //kd[u][k]=kd[v][k];
                    if(bs[v][k]){
                        bs[u][k]=1;
                    }
                }*/
                bs[u]|=bs[v];
            }
        }



        ans=0;
        for(int i=0;i<m;i++){
            int u=edge[i][0];
            int v=edge[i][1];

            for(int j=head[u];j!=-1;j=nextedge[j]){
                if(/*kd[to[j]][v]*/bs[to[j]][v]){
                    ans++;
                    break;
                }
            }
        }

        printf("%d\n",ans);
    }
}


转载于:https://www.cnblogs.com/ahahah/p/4918215.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值