zoukankan      html  css  js  c++  java
  • 大吉大利,晚上吃鸡!

    刚才打了一会(surviv),真的爽连吃三把。。。

    不皮了不皮了,我怎么可能打(surviv)这种东西呢?

    关于这道题,我风骨傲天愿称之为天天爱跑步·改!

    首先明确题意,对于任意的最短路径都必须经过(A)(B)且不能同时经过。

    不妨设(f[i])表示经过(i)的最短路。

    则一定有(f[A]+f[B]=f[T])

    先不急着处理这个式子,我们先考虑整体问题的处理方式。

    因为任意一条最短路一定经过(A)(B),所以我们不妨任意抽出一条最短路来做。

    我们发现,对于一个不在该路径上的点,它仅有可能和该路径上的一段点(连续)成为合法点对。

    如果我们统计所有不在该路径上但又在最短路径上的点与这条路径的点的答案,一定不会有遗漏。

    那我们就可以开个桶,内存(f[])的值,枚举最短路径上的点。

    先将左端点为(i)的加进桶中(此时他们可以开始产生影响)

    对于每个点,找到桶中(f[T]-f[i])的个数加进答案。

    然后再将右端点为(i)的删去(此时他们不会再产生贡献了)

    至于求(f)和那一段点,分别两边(Dijstra)和两边拓扑就好了。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    inline int read()
    {
        int f=1,w=0;char x=0;
        while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
        while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
        return w*f;
    }
    const int N=5e5+10;
    map<int,int> MP;
    vector<int> LL[N],RR[N];
    int num_edge,n,m,S,T,Sum,ans;
    int Dis[N][2],Vis[N],Dag[N],R[N],f[N];
    int head[N<<1],Cnt[N][2],Nex[N],L[N],Rod[N];
    struct Edge{int next,to,dis;} edge[N<<1];
    inline void Add(int from,int to,int dis)
    {
    	edge[++num_edge].next=head[from];
    	edge[num_edge].dis=dis;
    	edge[num_edge].to=to;
    	head[from]=num_edge;
    }
    inline void Dijstra_For_Count(int X,int Typ)
    {
    	priority_queue<pair<int,int> > Q;
    	Q.push(make_pair(0,X));
    	memset(Vis,0,sizeof(Vis));
    	memset(Nex,0,sizeof(Nex));
    	Cnt[X][Typ]=1,Dis[X][Typ]=0;
    	while(Q.size())
    	{
    		int x=Q.top().second;Q.pop();
    		if(Vis[x]) continue;Vis[x]=1;
    		for(int i=head[x];i;i=edge[i].next)
    			if(Dis[edge[i].to][Typ]>Dis[x][Typ]+edge[i].dis)
    			{
    				Dis[edge[i].to][Typ]=Dis[x][Typ]+edge[i].dis;
    				Cnt[edge[i].to][Typ]=Cnt[x][Typ],Nex[edge[i].to]=x;
    				Q.push(make_pair(Dis[edge[i].to][Typ],edge[i].to));
    			}
    			else if(Dis[edge[i].to][Typ]==Dis[x][Typ]+edge[i].dis)
    					Cnt[edge[i].to][Typ]+=Cnt[x][Typ];
    	}
    }
    inline void TopSort(int Typ)
    {
    	memset(Dag,0,sizeof(Dag));
    	queue<int> Q;
    	for(int i=1;i<=n;i++)
    		for(int j=head[i];j;j=edge[j].next)
    			if(Dis[edge[j].to][Typ^1]+Dis[i][Typ]+edge[j].dis==Dis[0][T])
    				Dag[edge[j].to]++;
    	for(int i=1;i<=n;i++) if(!Dag[i]) Q.push(i);
    	while(Q.size())
    	{
    		int x=Q.front();Q.pop();
    		for(int i=head[x];i;i=edge[i].next)
    			if(Dis[edge[i].to][Typ^1]+Dis[x][Typ]+edge[i].dis==Dis[0][T])
    			{
    				if(!(--Dag[edge[i].to])) Q.push(edge[i].to);
    				if(!Typ) L[edge[i].to]=max(L[edge[i].to],L[x]);
    				else R[edge[i].to]=min(R[edge[i].to],L[x]);
    			}
    	}
    }
    signed main(){
    #ifndef ONLINE_JUDGE
        freopen("A.in","r",stdin);
    #endif
    	memset(Dis,0x3f,sizeof(Dis));
    	n=read(),m=read(),S=read(),T=read();
    	for(int i=1,u,v,d;i<=m;i++)
    		u=read(),v=read(),d=read(),Add(u,v,d),Add(v,u,d);
    	Dijstra_For_Count(S,0);Dijstra_For_Count(T,1);
    	if(!Cnt[T][0]) {printf("%lld
    ",n*(n-1)/2);return 0;}
    	for(int i=S;i;i=Nex[i]) Rod[++Sum]=i,L[i]=Sum+1,R[i]=Sum-1;
    	for(int i=1;i<=n;i++) if(!L[i]&&!R[i]) L[i]=1,R[i]=Sum;
    	TopSort(0);TopSort(1);
    	for(int i=1;i<=n;i++)
    	{
    		if(Dis[i][0]+Dis[i][1]==Dis[T][0]) f[i]=Cnt[i][0]*Cnt[i][1];
    		if(L[i]>R[i]) continue;LL[L[i]].push_back(i);RR[R[i]].push_back(i);
    	}
    	for(int i=1;i<=Sum;i++)
    	{
    		for(int j=0;j<(int)LL[i].size();j++) ++MP[f[LL[i][j]]];
    		ans+=MP[f[T]-f[Rod[i]]];
    		for(int j=0;j<(int)RR[i].size();j++) --MP[f[RR[i][j]]];
    	}
    	printf("%lld",ans);
    }	
    
  • 相关阅读:
    LINUX内核参数调优集锦
    性能测试基础-开门篇3(LR常用函数介绍)
    高并发WEB服务的演变
    数据链路层学习之LLDP
    Win8.1 Metro应用无法联网终极解决方法
    Win8.1 Metro应用无法联网,提示“无法加载此页面”解决方法!(看红色字体部分)
    SecureCrt脚本(三)二级对象之Screen详解
    SecureCrt自动化
    Python数据类型一:数字与运算符
    高阶函数
  • 原文地址:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/11823136.html
Copyright © 2011-2022 走看看