zoukankan      html  css  js  c++  java
  • [Ctsc2015]misc

    https://lydsy.com/JudgeOnline/problem.php?id=4055

    题解

    观察题目要我们求的东西:

    [ans[k]=sum_{i}sum_j frac{a_i*a_j*f_k[i][j]}{f[i][j]} ]

    然后我们可以先枚举i,然后对于那个带限制的最短路部分,我们可以把贡献拆成两部分来计算。

    [ans[k]=sum_{i}a_i*f[i][k]sum_jfrac{a_j*f[k][j]}{f[i][j]} ]

    由于我们还要满足最短路的限制,所以我们可以先对每个i建出以i为源点的最短路(DAG)然后再(DAG)上维护后面的求和就可以了,这样可以保证是合法的。

    Warning

    维护f数组时注意一开始为了转移将(f[i][i]=1),最后做完了记得清空。

    代码

    #include<bits/stdc++.h>
    #define N 1009
    #define M 4009
    #define mm make_pair
    using namespace std;
    typedef long long ll;
    int head[N],tot,dis[N],du[N],n,m;
    bool vis[N];
    vector<int>vec[N];
    vector<int>::iterator it;
    priority_queue<pair<int,int> >q; 
    long double cnt[N][N],g[N],ans[N],a[N];
    inline ll rd(){
    	ll x=0;char c=getchar();bool f=0;
    	while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f?-x:x;
    }
    struct edge{
    	int n,to,l;double f;
    }e[M<<1];
    inline void add(int u,int v,int l,double f){
    	e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].f=f;e[tot].l=l;
    }
    inline void link(int i,int u){
    	vec[u].push_back(i);du[e[i].to]++;
    }
    inline void dij(int s){
    	memset(dis,0x3f,sizeof(dis));
    	memset(vis,0,sizeof(vis));
    	q.push(mm(0,s));cnt[s][s]=1;dis[s]=0;
    	while(!q.empty()){
    		int u=q.top().second;q.pop();
    		if(vis[u])continue;
    		vis[u]=1;
    		for(int i=head[u];i;i=e[i].n){
    			int v=e[i].to;
    			if(dis[v]>dis[u]+e[i].l){
    				dis[v]=dis[u]+e[i].l;
    				cnt[s][v]=cnt[s][u]*e[i].f; 
    			    q.push(mm(-dis[v],v));
    			}
    			else if(dis[v]==dis[u]+e[i].l)cnt[s][v]+=cnt[s][u]*e[i].f;
    		}
    	}
    }
    inline void topsort(int s){
    	memset(g,0,sizeof(g));
    	queue<int>q;
    	for(int i=1;i<=n;++i)if(!du[i])q.push(i);
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		ans[u]+=a[s]*cnt[s][u]*g[u];
    		g[u]+=a[u]/cnt[s][u];
    		for(it=vec[u].begin();it!=vec[u].end();++it){
    			int i=*it,v=e[i].to;
    			if(!--du[v])q.push(v);
    			g[v]+=g[u]*e[i].f;
    		}
    	}
    }
    int main(){
    	n=rd();m=rd();
    	for(int i=1;i<=n;++i)a[i]=rd();
    	int u,v,l;double f;tot=1;
    	for(int i=1;i<=m;++i){
    		u=rd();v=rd();l=rd();scanf("%lf",&f);
    		add(u,v,l,f);add(v,u,l,f);
    	}
    	for(int s=1;s<=n;++s){
    		dij(s);
    		cnt[s][s]=0;
    		for(int u=1;u<=n;++u)
    		  for(int i=head[u];i;i=e[i].n)if(dis[u]+e[i].l==dis[e[i].to])link(i^1,e[i].to);
    		topsort(s);
    		for(int u=1;u<=n;++u)vec[u].clear();
    	}
    	for(int i=1;i<=n;++i)printf("%.8Lf
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    shared_ptr weak_ptr boost 内存管理
    _vimrc win7 gvim
    qt 拖放
    数学小魔术 斐波那契数列
    qt4 程序 移植到 qt5
    (转)字符串匹配算法总结
    c++11
    BM 字符串匹配
    编译qt5 demo
    c++ 类库 学习资源
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10816244.html
Copyright © 2011-2022 走看看