zoukankan      html  css  js  c++  java
  • 【spfa】bzoj3921 Mimori与树海

    考虑“删除后图仍连通”,即其不是无向图的桥(bridge),可以用Tarjan算法预处理,这里不赘述。

    【算法一】

    枚举删除的是哪条边,然后枚举起点,暴搜,统计答案。

    可以通过01号测试点。

    预计得分:20分。

    【算法二】

    枚举删除的是哪条边,接着,

    ①枚举起点,∵op=0,∴裸最短路,Heap-dijkstra/SPFA。时间复杂度: O(m2*n*logn)/O(m2*n*k)

    Floyd,时间复杂度O(m*n3)

    可以通过0123号测试点。

    预计得分:40分。

    【算法三】

    枚举删的是哪条边,接着,枚举终点,逆着推回去,考虑op=1的边,则有w[U][V]=(dis[U]+18)/19。然后跑Heap-dijkstra/SPFA即可。

    时间复杂度:O(m2*n*logn)/O(m2*n*k)

    可以通过012345号测试点。

    预计得分:60分。

    【算法四】

    考虑删除某条边E后,以某个点U为终点的最短路是否发生变化。

    我们发现,在某个无向图中,以U为根节点,到其他所有点的最短路构成了一棵树,即“最短路树(shortest-path tree)”。我们删除的边如果不在最短路树上,对当前图中的以U为起点的所有最短路不发生变化。

    我们可以在Heap-dijkstra/SPFA的同时处理出最短路树:

    if(dis[V]>dis[U]+w[U][V]) TreeEdge[S][V]=Edge[U][V];

    //TreeEdge[S][V]表示以S为起点的单源最短路树中,V结点的父边。

    于是算法得出:

    首先枚举终点,然后枚举删除的边,仅仅需要重复求删除n-1条在最短路树上的边的答案即可,其他的边可以直接用之前预处理的答案就好了。

    时间复杂度:O(n2*m*logn)/O(n2*k*m)Heap-dijkstra可能需要卡常数。

    预计得分:100分。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    #define N 111
    #define M 1101
    queue<int>q;
    int dis[N],ans,ans2[M<<1],sumv[N],need[N];
    int n,m,first[N],next[M<<1],v[M<<1],en,TEs[N][N]/*树边*/,x,y,es[N][N];
    bool w[M<<1]/*道路类型*/,z,Del[M<<1]/*当前删除的边*/,ontree[N][M<<1]
    /*ontree[i][j]表示边j是否在以i为汇点的最短路树上*/,inq[N];
    void AddEdge(const int &U,const int &V,const bool &W)
    {
    	v[en]=V; w[en]=W;
    	next[en]=first[U];
    	first[U]=en;
    	es[U][V]=en++;
    }
    int calc(const int &U,const bool &op){return op ? (dis[U]+18)/19 : 1;}
    void spfa(const int &s,const bool &op)
    {
        memset(dis,0x7f,sizeof(dis));
        memset(inq,0,sizeof(inq));
        dis[s]=need[s]; inq[s]=1; q.push(s);
        while(!q.empty())
          {
            int U=q.front();
            for(int i=first[U];i!=-1;i=next[i]) if(!Del[i])
              {
              	int C=calc(U,w[i]);
              	if(dis[v[i]]>dis[U]+C)
                  {
                  	if(!op) TEs[s][v[i]]=es[U][v[i]];
                	dis[v[i]]=dis[U]+C;
                	if(!inq[v[i]])
                	  q.push(v[i]),inq[v[i]]=1;
                  }
              }
            q.pop(); inq[U]=0;
          }
        if(!op)
          {
          	for(int i=1;i<=n;++i)
          	  sumv[s]+=dis[i];
          	ans+=sumv[s];
          	for(int i=1;i<=n;++i)
    		  if(i!=s)
          	    ontree[s][TEs[s][i]]=ontree[s][TEs[s][i]^1]=1;
          }
    }
    int dfn[N],dep;
    bool bridge[M<<1];
    int Tarjan(int U,int fa)
    {
        int lowU=dfn[U]=++dep;
        for(int i=first[U];i!=-1;i=next[i])
          if(!dfn[v[i]])
    		{
              int lowV=Tarjan(v[i],U);
              lowU=min(lowU,lowV);
              if(lowV>dfn[U])
                bridge[i]=bridge[i^1]=1;
            }
          else if(v[i]!=fa)
    	    lowU=min(lowU,dfn[v[i]]);
        return lowU;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i) scanf("%d",&need[i]);
    	memset(first,-1,sizeof(first));
    	for(int i=1;i<=m;++i)
    	  {
    	  	scanf("%d%d%d",&x,&y,&z);
    	  	AddEdge(x,y,z);
    	  	AddEdge(y,x,z);
    	  }
    	Tarjan(1,0);
    	for(int i=1;i<=n;++i)
    	  spfa(i,0);
    	for(int i=1;i<=n;++i)
    	  {
    	  	for(int j=1;j<=n;++j)
    	  	  if((!bridge[TEs[i][j]])&&(j!=i))
    	  	    {
    	  	      Del[TEs[i][j]]=Del[TEs[i][j]^1]=1;
    	  	      spfa(i,1);
    	  	      Del[TEs[i][j]]=Del[TEs[i][j]^1]=0;
    	  	      int tmp=ans2[TEs[i][j]];
    	  	      for(int k=1;k<=n;++k)
    	  	        ans2[TEs[i][j]]+=dis[k];
    	  	      ans2[TEs[i][j]^1]+=(ans2[TEs[i][j]]-tmp);
    	  	    }
    	  	for(int j=0;j<en;++j)
    		  if((!bridge[j])&&(!ontree[i][j]))
    	  	    ans2[j]+=sumv[i];
    	  }
    	printf("%d %d
    ",ans,*max_element(ans2,ans2+en));
    	return 0;
    }
  • 相关阅读:
    python 解释器交互模块 -- sys
    python 操作系统模块 -- OS
    python 随机数模块 -- random
    python 时间模块 -- time
    Python 面向对象
    python 模块
    python -- 面向对象进阶
    github连接提示
    linux day4
    git基本使用
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4376093.html
Copyright © 2011-2022 走看看