HDU 2647 Reward(拓扑排序)


  • 原题链接:Here!

  • 分析:因为最近一直在做拓扑排序的问题,所以没多想就采用拓扑排序来解决这个问题,后来一想,跟并查集好像......
    1.判断图中是否存在环只需看能够处理多少节点,如果 处理节点数!=n,那肯定存在环。如果图中有环,那么在图中出现环的地方每个点的入度in[]肯定是无法=0的,所以环处的节点都不能进入队列,所以处理节点数目自然!=n。
    2.其次这个问题还需要计算需要至少需要多少钱,其实很简单,对于二元关系(a,b),a的工资比b多1元即可。按照这个想法那需要记下每个节点的"层数",一开始入度为0的点自然工资最低,即888,由这些点能够拓展得到的其他点只需要+1即可。
    3.一开始以为sum得挺大,用long long,后来验证一下发现sum最大5900w,int 足以。最坏是形成了一个链,888*n+(0+n-1)*n/2,n<=10000,5900w

  • CODE
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    //#define test
    
    const int maxn = 10000+10;
    int n,m;
    int topo[maxn];
    int in[maxn];
    vector<int> G[maxn];
    int sum;
    int arr[maxn];
    
    struct cmp{
    	bool operator()(int &a,int &b){
    		return a < b;
    	}
    };
    void topo_sort(){
    	queue<int> Q;
    	memset(arr,-1,sizeof(arr));
    	for(int i=1;i<=n;i++)
    		if(!in[i]){
    			Q.push(i);	arr[i]=0;
    		}
    	
    	while(!Q.empty()){	
    		int u=Q.front();	Q.pop();
    		topo[ ++topo[0] ]=u;
    		for(int v=0 ; v<G[u].size() ; v++){
    			in[ G[u][v] ]--;
    			if(in[ G[u][v] ]==0){
    				Q.push( G[u][v] );
    				arr[ G[u][v] ]=arr[u]+1;
    			}
    		}
    	}
    }
    int main(){
    	int a,b;
    	#ifdef	test
    		freopen("Hdu 2647.txt","r",stdin);
    	#endif
    	while(scanf("%d%d",&n,&m)!=EOF){
    		for(int i=1 ; i<=n ; i++)	G[i].clear();
    		memset(in,0,sizeof(in));
    		memset(topo,0,sizeof(topo));
    		
    		for(int i=1 ; i<=m ; i++){
    			scanf("%d%d",&a,&b);
    			G[b].push_back(a);	// b指向a 
    			in[a]++;
    		}
    		topo_sort();
    		sum=0;
    		if(topo[0]!=n)	printf("-1\n");
    		else{
    			for(int i=1 ; i<=n ; i++)	
    				sum+=arr[i];
    			printf("%d\n",sum+(n*888));
    		}
    	} 
    	return 0;
    }
    /*
    Test Data:
    5 4
    2 1
    3 2
    1 3
    1 4
    
    5 4
    3 2
    2 1
    1 4
    4 5
    
    3 1 
    1 2
    
    3 3 
    1 2 
    2 3 
    3 1
    
    4 4 
    1 2 
    2 3 
    1 4 
    3 4 
    */


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值