1. 程式人生 > >拓撲排序/DP【洛谷P2883】 [USACO07MAR]牛交通Cow Traffic

拓撲排序/DP【洛谷P2883】 [USACO07MAR]牛交通Cow Traffic

起點 排序。 add wap 瓶頸 push out 農場 using

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\n",ans);
    return 0;
}

拓撲排序/DP【洛谷P2883】 [USACO07MAR]牛交通Cow Traffic