codeforce Gym 100685F Flood (topo排序)

如果直接模拟水向周围流会TLE,因为某些个结点被重复扩展了多次,

科学做法是topo排序,每次只把入度为0的点放入队列,这样就严格保证了每个结点只被扩展一次。

#include<bits/stdc++.h>
using namespace std;
#define eps 1e-9
#define bug(x) cout<<#x<<'='<<x<<endl;
#define Min 1e-7
const int maxn = 1e4+4;
const int maxe = 1e5+5;

struct Ponds
{
    double cap,now;
};

typedef Ponds Pants;

Pants P[maxn];
int N,K;

vector<int> son[maxn];

int St,Tar,Amount;
int in[maxn];
queue<int> q;

void topo()
{

    P[St].now += Amount;
    q.push(St);
    for(int i = 1; i <= N; i++) if(!in[i] && i!= St) q.push(i);

    while(q.size()){
        int u = q.front(); q.pop();
        Pants &p = P[u];
        if(p.now - p.cap > 0){
            if(son[u].size()){
                double each = (p.now-p.cap)/son[u].size();
                 p.now = p.cap;
                for(int i = 0; i < son[u].size(); i++){
                    int v = son[u][i];
                    P[v].now += each;
                    if(--in[v] == 0 ) q.push(v);
                }
            }else {
                p.now = p.cap;
            }
        }

    }

}
int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d%d",&N,&K);
    for(int i = 1; i <= N; i++){
        scanf("%lf%lf",&P[i].cap,&P[i].now);
    }
    for(int i = 0; i < K; i++){
        int u,v; scanf("%d%d",&u,&v);
        son[u].push_back(v);
        in[v]++;
    }

    scanf("%d%d%d",&St,&Amount,&Tar);

    topo();
    printf("%lf",P[Tar].now);
    return 0;
}

 

posted @ 2015-08-05 09:45  陈瑞宇  阅读(341)  评论(0编辑  收藏  举报