zoukankan      html  css  js  c++  java
  • Luogu P2886 [USACO07NOV]牛继电器Cow Relays|最短路,倍增

    题目链接

    题意:给出一张无向连通图,求S到E经过N条边的最短路。

    数据范围:边数(le 100),顶点编号(le1000),(Nle1 imes 10^6)

    题解:

    最短路有三种解法,这种数据范围可使用(floyd)

    可以用(f[i][j][k])表示从(i)(j)经过(k)条边的最短路,显然TLE

    考虑倍增。预处理(K=2^k),此时(f[i][j][k]=min{f[i][l][k-1] + f[l][j][k-1]})

    (n)二进制拆分,显然第(x)位为(1),就直接调用(f[][][x])

    然后用几乎同样的方法就能求出经过(k)条边的最短路了。

    需要注意的是,按顶点跑(floyd)会超时,所以应该将其离散化。

    上代码

    #include<bits/stdc++.h>
    #define s(S) 1-S%2
    #define g(S) S%2
    using namespace std;
    const int oo=1000000000;
    int n,t,s,e,u,v,c,maxp;
    int f[1010][1010][20],ans[1010][1010][2],num[1010],snum;
    int main()
    {
    	cin>>n>>t>>s>>e;
    	num[s]=1;num[e]=2;snum=2;s=1;e=2;
    	for (int i=1;i<=t;i++)
    	{
    		cin>>c>>u>>v;
    		if (num[u]) u=num[u];else num[u]=++snum,u=num[u];
    		if (num[v]) v=num[v];else num[v]=++snum,v=num[v];
    		f[u][v][0]=f[v][u][0]=c;
    		maxp=max(maxp,max(u,v));
    	}	
    	for (int k=0;(1<<k)<=n;k++)
    	for (int i=1;i<=maxp;i++)
    	  for (int j=1;j<=maxp;j++)
    	  {
    	    if (k!=0||((!f[i][j][k]))) f[i][j][k]=oo;
    	  }
    	 for (int k=1;(1<<k)<=n;k++)
    	  for (int l=1;l<=maxp;l++)
    	    for (int i=1;i<=maxp;i++)
    	 	  for (int j=1;j<=maxp;j++)
    	 	  {
    	 		  f[i][j][k]=min(f[i][j][k],f[i][l][k-1]+f[l][j][k-1]);
    	 	  }//预处理
    	int S=0,sum=1,S1=0;
    	while (n&&!(n&1))
    	{
    		n>>=1;S1++;
    	}
    	for (int i=1;i<=maxp;i++)
    	 	for (int j=1;j<=maxp;j++)
    	 	{
    	 		ans[i][j][S]=f[i][j][S1];
    	 	}
    	n>>=1;S1++;
    	while (n&&!(n&1))
    	{
    		n>>=1;S1++;
    	}
    	for (int i=1;i<=maxp;i++)
    	  	for (int j=1;j<=maxp;j++)
    	  	{
    	  		ans[i][j][1]=oo;
    	  	}
    	while (n)
    	{
    		S++;S%=2;
    		for (int l=1;l<=maxp;l++)
    		for (int i=1;i<=maxp;i++)
    	 	for (int j=1;j<=maxp;j++)
    	 	{
    	 		ans[i][j][S]=min(ans[i][j][S],ans[i][l][s(S)]+f[l][j][S1]);
    	 	}
    		n>>=1;S1++;
    		while (n&&!(n&1))
    		{
    			n>>=1;S1++;
    		}
    	 	for (int i=1;i<=maxp;i++)
    	  	for (int j=1;j<=maxp;j++)
    	  	{
    	  		ans[i][j][s(S)]=oo;
    	  	}
    	}//求ans,与上面几乎一致
    	cout<<ans[s][e][S]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    51Nod 2006 飞行员配对(二分图最大匹配)-匈牙利算法
    51Nod 1212无向图最小生成树
    51Nod 1081前缀和
    51Nod 1118 机器人走方格--求逆元
    Java四种线程池的使用
    java常用的几种线程池比较
    一名3年工作经验的程序员应该具备的技能(写得很好,果断转)
    《深入理解mybatis原理》 MyBatis的架构设计以及实例分析
    javadoc
    java 反射机制 观点
  • 原文地址:https://www.cnblogs.com/fmj123/p/Luogu2886.html
Copyright © 2011-2022 走看看