zoukankan      html  css  js  c++  java
  • 拓扑排序/DP【洛谷P2883】 [USACO07MAR]牛交通Cow Traffic

    P2883 [USACO07MAR]牛交通Cow Traffic

    随着牛的数量增加,农场的道路的拥挤现象十分严重,特别是在每天晚上的挤奶时间。为了解决这个问题,FJ决定研究这个问题,以能找到导致拥堵现象的瓶颈所在。

    牧场共有M条单向道路,每条道路连接着两个不同的交叉路口,为了方便研究,FJ将这些交叉路口编号为1..N,而牛圈位于交叉路口N。任意一条单向道路的方向一定是是从编号低的路口到编号高的路口,因此农场中不会有环型路径。同时,可能存在某两个交叉路口不止一条单向道路径连接的情况。

    在挤奶时间到来的时候,奶牛们开始从各自的放牧地点回到牛圈。放牧地点是指那些没有道路连接进来的路口(入度为0的顶点)。

    现在请你帮助fj通过计算从放牧点到达牛圈的路径数目来找到最繁忙的道路(答案保证是不超过32位整数)。

    思维固化了。

    看到这题直接套上P1685 游览的板子。

    才得60分。

    再读题(看题解),发现这题会有多个起点,多个终点。

    那么对于多个终点,只能去n,所以还要从n建反边跑一边拓扑排序,这样一条边的贡献就是(g(u)*f(v))

    好像我用了最笨的方法跑两边拓扑排序。

    code:

    #include <iostream>
    #include <cstdio>
    #include <queue>
    
    using namespace std;
    
    const int wx=500017;
    
    inline int read(){
    	int sum=0,f=1; char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    	return sum*f;
    }
    
    int n,m,ans;
    int num,tot;
    int g[wx],head[wx],h[wx],f[wx];
    int in[wx],out[wx],in2[wx],out2[wx];
    
    struct e{
    	int nxt,to;
    }edge[wx*2];
    
    void add(int from,int to){
    	edge[++num].nxt=head[from];
    	edge[num].to=to;
    	head[from]=num;
    }
    
    struct ee{
    	int nxt,to;
    }e[wx*2];
    
    void ADD(int from,int to){
    	e[++tot].nxt=h[from];
    	e[tot].to=to;
    	h[from]=tot;
    }
    
    queue<int > q;
    
    void bfs1(){
    	for(int i=1;i<=n;i++)if(!in[i])g[i]=1,q.push(i);
    	while(q.size()){
    		int u=q.front(); q.pop();
    		for(int i=head[u];i;i=edge[i].nxt){
    			int v=edge[i].to;
    			g[v]+=g[u];
    			in[v]--;
    			if(!in[v]){
    				q.push(v);
    			}
    		}
    	}
    }
    
    void bfs2(){
    	for(int i=1;i<=n;i++)if(!in2[i])f[i]=1,q.push(i);
    	while(q.size()){
    		int u=q.front(); q.pop();
    		for(int i=h[u];i;i=e[i].nxt){
    			int v=e[i].to;
    			f[v]+=f[u];
    			in2[v]--;
    			if(!in2[v])q.push(v);
    		}
    	}
    	for(int u=1;u<=n;u++){
    		for(int i=head[u];i;i=edge[i].nxt){
    			int v=edge[i].to;
    			ans=max(ans,g[u]*f[v]);
    		}
    	}
    }
    
    int main(){
    	n=read(); m=read();
    	for(int i=1;i<=m;i++){
    		int x,y; 
    		x=read(); y=read();
    		if(x>y)swap(x,y);
    		add(x,y); in[y]++; out[x]++;
    		ADD(y,x); in2[x]++; out2[y]++;
    	}
    	bfs1();
    	bfs2();
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    li中下的a元素的字超出了li的宽度
    0 ‘+new Array(017)’ 输出? js+相当于Number()类型转换
    通过字体代替图片优化,如何使用Font Awesome字体图标?
    Array.prototype.slice.call()等几种将arguments对象转换成数组对象的方法
    js关于if()else{}中的判定条件的认识,各种数据类型转换为Boolean类型的转换规则
    js基本包装类型
    WordPress启用memcached动态缓存,弄了好久终于弄好了
    VsCode最实用插件集合
    Cordova--IOS打包问题汇总
    cordova--安卓打包
  • 原文地址:https://www.cnblogs.com/wangxiaodai/p/9811740.html
Copyright © 2011-2022 走看看