zoukankan      html  css  js  c++  java
  • 模拟赛 最小环 题解

    求包含1号点的最小环。

    这个最小环一定是从1点的出边指向的点出发,再回到另一个1点的出边指向的点。

    这等价于1号点所有出边指向的点中,两两之间最短路+1号点到这两个点的距离的最小值。

    使用二进制拆分,分成两组点,分别向s,t连边,正反算两次最短路。

    时间复杂度 (O((n+m)log^2 n))

    二进制分组是很常用的思路。

    参考代码:

    #include <stdio.h>
    #include <queue>
    using namespace std;
    int fr[5010],ne[30010],inf=999999999;
    int v[30010],w[30010],bs=0,n;
    int jl[5010],sz[5010],cd1[5010],cd2[5010];
    bool bk[5010];
    void addb(int a,int b,int c)
    {
    	v[bs]=b;
    	w[bs]=c;
    	ne[bs]=fr[a];
    	fr[a]=bs;
    	bs+=1;
    }
    struct SJd               
    {                        
        int u,z;
    	SJd(){};
    	SJd(int Z,int U)
    	{
    		z=Z;
    		u=U;
    	}
    	bool operator<(const SJd&a)const
    	{
    		return z>a.z;
    	}
    };
    int dij(int S,int T)
    {
    	for(int i=1;i<=n;i++)
    	{
    		bk[i]=false;
    		jl[i]=inf;
    	}
    	jl[S]=0;
    	priority_queue<SJd> dl;
    	dl.push(SJd(0,S));
        while(!(dl.empty()))
        {
    		SJd	t=dl.top();
    		dl.pop();
    		if(bk[t.u])
    			continue;
    		bk[t.u]=true;
            for(int j=fr[t.u];j!=-1;j=ne[j])                  
            {      
    			if(v[j]==1)
    				continue;
                if(t.z+w[j]<jl[v[j]])                        
                { 
    				jl[v[j]]=t.z+w[j];
                    dl.push(SJd(jl[v[j]],v[j]));
                }
            }                                                
        }
    	return jl[T];
    }
    int main()
    {
    	freopen("B.in","r",stdin);
    	freopen("B.out","w",stdout);
    	int m,k=0,jg=inf;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n+2;i++)
    		fr[i]=-1;
    	for(int i=0;i<m;i++)
    	{
    		int a,b,c,d;
    		scanf("%d%d%d%d",&a,&b,&c,&d);
    		addb(a,b,c);
    		addb(b,a,d);
    	}
    	for(int i=fr[1];i!=-1;i=ne[i])
    	{
    		sz[k]=v[i];
    		cd1[k]=w[i];
    		cd2[k]=w[i^1];
    		k+=1;
    	}
    	n+=2;
    	for(int i=16;i>=0;i--)
    	{
    		for(int j=0;j<k;j++)
    		{
    			if(j&(1<<i))
    			{
    				addb(n,sz[j],cd1[j]);
    				addb(sz[j],n,cd1[j]);
    			}
    			else
    			{
    				addb(n-1,sz[j],cd2[j]);
    				addb(sz[j],n-1,cd2[j]);
    			}
    		}
    		int rt=dij(n,n-1);
    		if(rt<jg)
    			jg=rt;
    		bs-=k*2;
    		for(int j=0;j<k;j++)
    			fr[sz[j]]=ne[fr[sz[j]]];
    		fr[n]=fr[n-1]=-1;
    		//
    		for(int j=0;j<k;j++)
    		{
    			if(!(j&(1<<i)))
    			{
    				addb(n,sz[j],cd1[j]);
    				addb(sz[j],n,cd1[j]);
    			}
    			else
    			{
    				addb(n-1,sz[j],cd2[j]);
    				addb(sz[j],n-1,cd2[j]);
    			}
    		}
    		rt=dij(n,n-1);
    		if(rt<jg)
    			jg=rt;
    		bs-=k*2;
    		for(int j=0;j<k;j++)
    			fr[sz[j]]=ne[fr[sz[j]]];
    		fr[n]=fr[n-1]=-1;
    	}
    	printf("%d",jg);
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Java Bean validation specification...
    javascript压缩工具:YUI compressor
    CSS: Float a div on another div, Ex: Text caption on picture
    汉文博士 0.5.3.1944 测试版发布
    简单记事本程序java源码项目
    Windows计算机功能Java源码
    HighCharts 图表插件 自定义绑定 时间轴数据
    Windows Phone 8.1 新特性
    可自定义导航条功能案例ios项目源码
    自动计算尺寸列表功能案例ios源码
  • 原文地址:https://www.cnblogs.com/lnzwz/p/11246797.html
Copyright © 2011-2022 走看看